omegaconf 2.4.0.dev13__tar.gz → 2.4.0.dev14__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.dev13/omegaconf.egg-info → omegaconf-2.4.0.dev14}/PKG-INFO +2 -5
- omegaconf-2.4.0.dev14/build_helpers/__init__.py +5 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/build_helpers/get_vendored.py +46 -30
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/__init__.py +1 -2
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/_utils.py +273 -31
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/base.py +134 -21
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/basecontainer.py +105 -29
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/dictconfig.py +11 -2
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/grammar_visitor.py +2 -1
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/listconfig.py +27 -18
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/nodes.py +42 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/omegaconf.py +414 -54
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/version.py +1 -1
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14/omegaconf.egg-info}/PKG-INFO +2 -5
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf.egg-info/SOURCES.txt +2 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf.egg-info/requires.txt +1 -4
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/pyproject.toml +21 -27
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/requirements/dev.txt +1 -4
- omegaconf-2.4.0.dev14/setup.cfg +7 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/__init__.py +0 -5
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/interpolation/test_custom_resolvers.py +3 -1
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/interpolation/test_interpolation.py +10 -5
- omegaconf-2.4.0.dev14/tests/interpolation/test_resolver_annotation_validation.py +522 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/structured_conf/data/attr_classes.py +21 -1
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/structured_conf/data/dataclasses.py +23 -1
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/structured_conf/data/dataclasses_pre_311.py +23 -1
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/structured_conf/test_structured_basic.py +375 -3
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/structured_conf/test_structured_config.py +41 -4
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_basic_ops_dict.py +12 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_basic_ops_list.py +69 -2
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_container_unions.py +17 -20
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_create.py +12 -6
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_errors.py +3 -14
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_merge.py +144 -50
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_nodes.py +6 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_omegaconf.py +5 -0
- omegaconf-2.4.0.dev14/tests/test_structured_config_unions.py +614 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_tuple_merge.py +1 -16
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_unions.py +73 -2
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_update.py +283 -2
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_utils.py +39 -3
- omegaconf-2.4.0.dev13/build_helpers/__init__.py +0 -3
- omegaconf-2.4.0.dev13/setup.cfg +0 -12
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/LICENSE +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/MANIFEST.in +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/README.md +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/build_helpers/bin/antlr-4.11.1-complete.jar +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/build_helpers/build_helpers.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/build_helpers/test_helpers.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/_impl.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/_yaml.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/errors.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/grammar/OmegaConfGrammarLexer.g4 +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/grammar/OmegaConfGrammarParser.g4 +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/grammar/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/grammar/gen/OmegaConfGrammarLexer.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/grammar/gen/OmegaConfGrammarParser.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/grammar/gen/OmegaConfGrammarParserListener.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/grammar/gen/OmegaConfGrammarParserVisitor.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/grammar/gen/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/grammar_parser.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/py.typed +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/resolvers/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/resolvers/oc/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/resolvers/oc/dict.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/tupleconfig.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/typing.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/BufferedTokenStream.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/CommonTokenFactory.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/CommonTokenStream.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/FileStream.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/InputStream.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/IntervalSet.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/LL1Analyzer.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/Lexer.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/ListTokenSource.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/Parser.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/ParserInterpreter.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/ParserRuleContext.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/PredictionContext.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/Recognizer.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/RuleContext.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/StdinStream.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/Token.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/TokenStreamRewriter.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/Utils.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/_pygrun.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/ATN.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/ATNConfig.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/ATNConfigSet.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/ATNDeserializationOptions.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/ATNDeserializer.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/ATNSimulator.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/ATNState.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/ATNType.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/LexerATNSimulator.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/LexerAction.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/LexerActionExecutor.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/ParserATNSimulator.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/PredictionMode.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/SemanticContext.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/Transition.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/atn/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/dfa/DFA.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/dfa/DFASerializer.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/dfa/DFAState.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/dfa/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/error/DiagnosticErrorListener.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/error/ErrorListener.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/error/ErrorStrategy.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/error/Errors.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/error/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/tree/Chunk.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/tree/ParseTreeMatch.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/tree/ParseTreePattern.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/tree/ParseTreePatternMatcher.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/tree/RuleTagToken.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/tree/TokenTagToken.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/tree/Tree.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/tree/Trees.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/tree/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/xpath/XPath.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/xpath/XPathLexer.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf/vendor/antlr4/xpath/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf.egg-info/dependency_links.txt +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/omegaconf.egg-info/top_level.txt +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/requirements/base.txt +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/requirements/docs.txt +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/setup.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/conftest.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/data/2.0.6.pickle +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/data/2.1.0.rc1.pickle +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/data/load.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/data/save.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/examples/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/examples/dataclass_postponed_annotations.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/examples/test_dataclass_example.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/examples/test_postponed_annotations.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/interpolation/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/interpolation/built_in_resolvers/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/interpolation/built_in_resolvers/test_oc_create.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/interpolation/built_in_resolvers/test_oc_decode.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/interpolation/built_in_resolvers/test_oc_deprecated.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/interpolation/built_in_resolvers/test_oc_dict.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/interpolation/built_in_resolvers/test_oc_env.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/interpolation/built_in_resolvers/test_oc_select.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/structured_conf/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/structured_conf/data/__init__.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_base_config.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_basic_ops_tuple.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_compare_dictconfig_vs_dict.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_config_eq.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_get_full_key.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_grammar.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_matrix.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_nested_containers.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_readonly.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_select.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_serialization.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_struct.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_to_container.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_to_yaml.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_tuple_integration.py +0 -0
- {omegaconf-2.4.0.dev13 → omegaconf-2.4.0.dev14}/tests/test_tuple_structured.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.dev14
|
|
4
4
|
Summary: A flexible configuration library
|
|
5
5
|
Home-page: https://github.com/omry/omegaconf
|
|
6
6
|
Author: Omry Yadan
|
|
@@ -22,19 +22,16 @@ Requires-Dist: PyYAML>=5.1.0; extra == "dev"
|
|
|
22
22
|
Requires-Dist: sphinx; extra == "dev"
|
|
23
23
|
Requires-Dist: sphinx-tabs; extra == "dev"
|
|
24
24
|
Requires-Dist: attrs; extra == "dev"
|
|
25
|
-
Requires-Dist: black[jupyter]==26.3.1; extra == "dev"
|
|
26
25
|
Requires-Dist: build; extra == "dev"
|
|
27
26
|
Requires-Dist: bump-my-version; extra == "dev"
|
|
28
27
|
Requires-Dist: coveralls; extra == "dev"
|
|
29
|
-
Requires-Dist: flake8==7.3.0; extra == "dev"
|
|
30
|
-
Requires-Dist: isort==5.13.2; extra == "dev"
|
|
31
28
|
Requires-Dist: nox[pbs]; extra == "dev"
|
|
32
29
|
Requires-Dist: pre-commit; extra == "dev"
|
|
33
|
-
Requires-Dist: pyflakes; extra == "dev"
|
|
34
30
|
Requires-Dist: pyrefly==0.62.0; extra == "dev"
|
|
35
31
|
Requires-Dist: pytest; extra == "dev"
|
|
36
32
|
Requires-Dist: pytest-benchmark; extra == "dev"
|
|
37
33
|
Requires-Dist: pytest-mock; extra == "dev"
|
|
34
|
+
Requires-Dist: ruff==0.15.22; extra == "dev"
|
|
38
35
|
Requires-Dist: towncrier; extra == "dev"
|
|
39
36
|
Requires-Dist: twine; extra == "dev"
|
|
40
37
|
Requires-Dist: pydevd; extra == "dev"
|
|
@@ -6,10 +6,12 @@ from itertools import chain
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from typing import Callable, FrozenSet, Generator, List, Set, Tuple, Union
|
|
8
8
|
|
|
9
|
-
WHITELIST = {
|
|
9
|
+
WHITELIST = {"README.txt", "__init__.py", "vendor.txt"}
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
def delete_all(
|
|
12
|
+
def delete_all(
|
|
13
|
+
*paths: Path, whitelist: Union[Set[str], FrozenSet[str]] = frozenset()
|
|
14
|
+
) -> None:
|
|
13
15
|
"""Clear all the items in each of the indicated paths, except for elements listed
|
|
14
16
|
in the whitelist"""
|
|
15
17
|
for item in paths:
|
|
@@ -34,13 +36,15 @@ def iter_subtree(path: Path, depth: int = 0) -> Generator[Tuple[Path, int], None
|
|
|
34
36
|
|
|
35
37
|
def patch_vendor_imports(file: Path, replacements: List[Callable[[str], str]]) -> None:
|
|
36
38
|
"""Apply a list of replacements/patches to a given file"""
|
|
37
|
-
text = file.read_text(
|
|
39
|
+
text = file.read_text("utf8")
|
|
38
40
|
for replacement in replacements:
|
|
39
41
|
text = replacement(text)
|
|
40
|
-
file.write_text(text,
|
|
42
|
+
file.write_text(text, "utf8")
|
|
41
43
|
|
|
42
44
|
|
|
43
|
-
def find_vendored_libs(
|
|
45
|
+
def find_vendored_libs(
|
|
46
|
+
vendor_dir: Path, whitelist: Set[str]
|
|
47
|
+
) -> Tuple[List[str], List[Path]]:
|
|
44
48
|
vendored_libs = []
|
|
45
49
|
paths = []
|
|
46
50
|
for item in vendor_dir.iterdir():
|
|
@@ -56,23 +60,31 @@ def find_vendored_libs(vendor_dir: Path, whitelist: Set[str]) -> Tuple[List[str]
|
|
|
56
60
|
|
|
57
61
|
def vendor(vendor_dir: Path, relative_imports: bool = False) -> None:
|
|
58
62
|
# target package is <parent>.<vendor_dir>; foo/vendor -> foo.vendor
|
|
59
|
-
pkgname = f
|
|
63
|
+
pkgname = f"{vendor_dir.parent.name}.{vendor_dir.name}"
|
|
60
64
|
|
|
61
65
|
# remove everything
|
|
62
66
|
delete_all(*vendor_dir.iterdir(), whitelist=WHITELIST)
|
|
63
67
|
|
|
64
68
|
# install with pip
|
|
65
|
-
subprocess.run(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
subprocess.run(
|
|
70
|
+
[
|
|
71
|
+
"pip",
|
|
72
|
+
"install",
|
|
73
|
+
"-t",
|
|
74
|
+
str(vendor_dir),
|
|
75
|
+
"-r",
|
|
76
|
+
str(vendor_dir / "vendor.txt"),
|
|
77
|
+
"--no-compile",
|
|
78
|
+
"--no-deps",
|
|
79
|
+
]
|
|
80
|
+
)
|
|
70
81
|
|
|
71
82
|
# delete stuff that's not needed
|
|
72
83
|
delete_all(
|
|
73
|
-
*vendor_dir.glob(
|
|
74
|
-
*vendor_dir.glob(
|
|
75
|
-
vendor_dir /
|
|
84
|
+
*vendor_dir.glob("*.dist-info"),
|
|
85
|
+
*vendor_dir.glob("*.egg-info"),
|
|
86
|
+
vendor_dir / "bin",
|
|
87
|
+
)
|
|
76
88
|
|
|
77
89
|
vendored_libs, paths = find_vendored_libs(vendor_dir, WHITELIST)
|
|
78
90
|
|
|
@@ -81,41 +93,45 @@ def vendor(vendor_dir: Path, relative_imports: bool = False) -> None:
|
|
|
81
93
|
for lib in vendored_libs:
|
|
82
94
|
replacements += (
|
|
83
95
|
partial( # import bar -> import foo.vendor.bar
|
|
84
|
-
re.compile(r
|
|
85
|
-
r
|
|
96
|
+
re.compile(r"(^\s*)import {}\n".format(lib), flags=re.M).sub,
|
|
97
|
+
r"\1from {} import {}\n".format(pkgname, lib),
|
|
86
98
|
),
|
|
87
99
|
partial( # from bar -> from foo.vendor.bar
|
|
88
|
-
re.compile(r
|
|
89
|
-
r
|
|
100
|
+
re.compile(r"(^\s*)from {}(\.|\s+)".format(lib), flags=re.M).sub,
|
|
101
|
+
r"\1from {}.{}\2".format(pkgname, lib),
|
|
90
102
|
),
|
|
91
103
|
)
|
|
92
104
|
|
|
93
105
|
for file, depth in chain.from_iterable(map(iter_subtree, paths)):
|
|
94
106
|
if relative_imports:
|
|
95
|
-
pkgname =
|
|
107
|
+
pkgname = "." * (depth - 1)
|
|
96
108
|
replacements = []
|
|
97
109
|
for lib in vendored_libs:
|
|
98
110
|
replacements += (
|
|
99
111
|
partial(
|
|
100
|
-
re.compile(r
|
|
101
|
-
r
|
|
112
|
+
re.compile(r"(^\s*)import {}\n".format(lib), flags=re.M).sub,
|
|
113
|
+
r"\1from {} import {}\n".format(pkgname, ""),
|
|
102
114
|
),
|
|
103
115
|
partial(
|
|
104
|
-
re.compile(r
|
|
105
|
-
r
|
|
116
|
+
re.compile(r"^from {}(\s+)".format(lib), flags=re.M).sub,
|
|
117
|
+
r"from .{}\1".format(pkgname),
|
|
106
118
|
),
|
|
107
119
|
partial(
|
|
108
|
-
re.compile(r
|
|
109
|
-
r
|
|
120
|
+
re.compile(r"(^\s*)from {}(\.+)".format(lib), flags=re.M).sub,
|
|
121
|
+
r"\1from {}\2".format(pkgname),
|
|
110
122
|
),
|
|
111
123
|
)
|
|
112
124
|
patch_vendor_imports(file, replacements)
|
|
113
125
|
|
|
114
126
|
|
|
115
|
-
if __name__ ==
|
|
127
|
+
if __name__ == "__main__":
|
|
116
128
|
# this assumes this is a script in `build_helpers`
|
|
117
|
-
|
|
118
|
-
vendor_dir =
|
|
119
|
-
assert (vendor_dir /
|
|
120
|
-
|
|
129
|
+
repo_root = Path(__file__).resolve().parent.parent
|
|
130
|
+
vendor_dir = repo_root / "omegaconf" / "vendor"
|
|
131
|
+
assert (vendor_dir / "vendor.txt").exists(), (
|
|
132
|
+
"omegaconf/vendor/vendor.txt file not found"
|
|
133
|
+
)
|
|
134
|
+
assert (vendor_dir / "__init__.py").exists(), (
|
|
135
|
+
"omegaconf/vendor/__init__.py file not found"
|
|
136
|
+
)
|
|
121
137
|
vendor(vendor_dir, relative_imports=True)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from .base import Container, DictKeyType,
|
|
1
|
+
from .base import Container, DictKeyType, Node, SCMode, UnionNode
|
|
2
2
|
from .dictconfig import DictConfig
|
|
3
3
|
from .errors import (
|
|
4
4
|
KeyValidationError,
|
|
@@ -50,7 +50,6 @@ __all__ = [
|
|
|
50
50
|
"OmegaConf",
|
|
51
51
|
"Resolver",
|
|
52
52
|
"SCMode",
|
|
53
|
-
"ListMergeMode",
|
|
54
53
|
"flag_override",
|
|
55
54
|
"read_write",
|
|
56
55
|
"open_dict",
|
|
@@ -52,6 +52,8 @@ if TYPE_CHECKING:
|
|
|
52
52
|
import attr
|
|
53
53
|
from attr import Attribute as AttrAttribute
|
|
54
54
|
|
|
55
|
+
from .basecontainer import BaseContainer
|
|
56
|
+
|
|
55
57
|
|
|
56
58
|
NoneType: Type[None] = type(None)
|
|
57
59
|
|
|
@@ -230,26 +232,130 @@ def is_union_annotation(type_: Any) -> bool:
|
|
|
230
232
|
return getattr(type_, "__origin__", None) is Union
|
|
231
233
|
|
|
232
234
|
|
|
233
|
-
def
|
|
234
|
-
"""Check whether `type_` is equivalent to `typing.Optional[T]` for some T."""
|
|
235
|
+
def _resolve_type_alias(type_: Any) -> Any:
|
|
235
236
|
if sys.version_info >= (3, 12): # pragma: no cover
|
|
236
237
|
import typing # lgtm [py/import-and-import-from]
|
|
237
238
|
|
|
238
|
-
|
|
239
|
-
|
|
239
|
+
seen = set()
|
|
240
|
+
while id(type_) not in seen:
|
|
241
|
+
seen.add(id(type_))
|
|
242
|
+
if isinstance(type_, typing.TypeAliasType):
|
|
243
|
+
bare_alias = True
|
|
244
|
+
origin = type_
|
|
245
|
+
arguments: Tuple[Any, ...] = ()
|
|
246
|
+
else:
|
|
247
|
+
bare_alias = False
|
|
248
|
+
origin = typing.get_origin(type_)
|
|
249
|
+
if not isinstance(origin, typing.TypeAliasType):
|
|
250
|
+
break
|
|
251
|
+
arguments = typing.get_args(type_)
|
|
252
|
+
|
|
253
|
+
parameters = origin.__type_params__
|
|
254
|
+
variadic = [
|
|
255
|
+
parameter
|
|
256
|
+
for parameter in parameters
|
|
257
|
+
if isinstance(parameter, typing.TypeVarTuple)
|
|
258
|
+
]
|
|
259
|
+
if len(variadic) > 1:
|
|
260
|
+
break
|
|
261
|
+
|
|
262
|
+
if bare_alias:
|
|
263
|
+
substitutions = {}
|
|
264
|
+
elif variadic:
|
|
265
|
+
variadic_index = parameters.index(variadic[0])
|
|
266
|
+
trailing = len(parameters) - variadic_index - 1
|
|
267
|
+
if len(arguments) < len(parameters) - 1:
|
|
268
|
+
break
|
|
269
|
+
substitutions = dict(zip(parameters[:variadic_index], arguments))
|
|
270
|
+
substitutions[variadic[0]] = arguments[
|
|
271
|
+
variadic_index : len(arguments) - trailing if trailing else None
|
|
272
|
+
]
|
|
273
|
+
if trailing:
|
|
274
|
+
substitutions.update(
|
|
275
|
+
zip(parameters[-trailing:], arguments[-trailing:])
|
|
276
|
+
)
|
|
277
|
+
else:
|
|
278
|
+
if len(arguments) > len(parameters):
|
|
279
|
+
break
|
|
280
|
+
substitutions = dict(zip(parameters, arguments))
|
|
281
|
+
|
|
282
|
+
def substitution_args(value: Any) -> Tuple[Any, ...]:
|
|
283
|
+
result = []
|
|
284
|
+
for parameter in getattr(value, "__parameters__", ()):
|
|
285
|
+
argument = substitutions[parameter]
|
|
286
|
+
if isinstance(parameter, typing.TypeVarTuple):
|
|
287
|
+
result.extend(argument)
|
|
288
|
+
else:
|
|
289
|
+
result.append(argument)
|
|
290
|
+
return tuple(result)
|
|
291
|
+
|
|
292
|
+
no_default = getattr(typing, "NoDefault", None)
|
|
293
|
+
for parameter in parameters:
|
|
294
|
+
if parameter in substitutions:
|
|
295
|
+
continue
|
|
296
|
+
default: Any = getattr(parameter, "__default__", no_default)
|
|
297
|
+
if default is no_default:
|
|
298
|
+
break
|
|
299
|
+
|
|
300
|
+
for known_parameter, argument in substitutions.items():
|
|
301
|
+
if default is known_parameter:
|
|
302
|
+
default = argument
|
|
303
|
+
break
|
|
304
|
+
else:
|
|
305
|
+
default_parameters = getattr(default, "__parameters__", ())
|
|
306
|
+
if default_parameters:
|
|
307
|
+
try:
|
|
308
|
+
default_arguments = substitution_args(default)
|
|
309
|
+
except KeyError:
|
|
310
|
+
break
|
|
311
|
+
default = default[default_arguments]
|
|
312
|
+
if isinstance(parameter, typing.TypeVarTuple):
|
|
313
|
+
default_args = typing.get_args(default)
|
|
314
|
+
if typing.get_origin(default) is typing.Unpack and default_args:
|
|
315
|
+
default = typing.get_args(default_args[0])
|
|
316
|
+
substitutions[parameter] = default
|
|
317
|
+
else:
|
|
318
|
+
value = origin.__value__
|
|
319
|
+
for parameter, argument in substitutions.items():
|
|
320
|
+
if value is parameter:
|
|
321
|
+
value = argument
|
|
322
|
+
break
|
|
323
|
+
else:
|
|
324
|
+
value_parameters = getattr(value, "__parameters__", ())
|
|
325
|
+
if value_parameters:
|
|
326
|
+
try:
|
|
327
|
+
value_arguments = substitution_args(value)
|
|
328
|
+
except KeyError:
|
|
329
|
+
break
|
|
330
|
+
value = value[value_arguments]
|
|
331
|
+
type_ = value
|
|
332
|
+
continue
|
|
333
|
+
break
|
|
334
|
+
return type_
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def _resolve_optional(type_: Any) -> Tuple[bool, Any]:
|
|
338
|
+
"""Normalize aliases and check whether `type_` accepts None."""
|
|
339
|
+
type_ = _resolve_type_alias(type_)
|
|
240
340
|
if is_union_annotation(type_):
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
341
|
+
optional = False
|
|
342
|
+
args = []
|
|
343
|
+
for arg in type_.__args__:
|
|
344
|
+
arg_optional, arg_type = _resolve_optional(arg)
|
|
345
|
+
if arg_type is Any:
|
|
346
|
+
return True, Any
|
|
347
|
+
optional = optional or arg_optional
|
|
348
|
+
if arg_type is NoneType:
|
|
349
|
+
continue
|
|
350
|
+
args.append(arg_type)
|
|
351
|
+
|
|
247
352
|
if len(args) == 1:
|
|
248
353
|
return optional, args[0]
|
|
249
354
|
elif len(args) >= 2:
|
|
250
|
-
return optional, Union[args]
|
|
355
|
+
return optional, Union[tuple(args)] # pyrefly: ignore[not-a-type]
|
|
251
356
|
else:
|
|
252
|
-
|
|
357
|
+
# Only distinct PEP 695 aliases that all resolve to None can reach this.
|
|
358
|
+
return True, NoneType # pragma: no cover
|
|
253
359
|
|
|
254
360
|
if type_ is Any:
|
|
255
361
|
return True, Any
|
|
@@ -271,30 +377,111 @@ def _is_optional(obj: Any, key: Optional[Union[int, str]] = None) -> bool:
|
|
|
271
377
|
return obj._is_optional()
|
|
272
378
|
|
|
273
379
|
|
|
274
|
-
def _resolve_forward(
|
|
380
|
+
def _resolve_forward(
|
|
381
|
+
type_: Type[Any],
|
|
382
|
+
module: str,
|
|
383
|
+
preserve_container_origin: bool = False,
|
|
384
|
+
type_alias_guard: Optional[set[int]] = None,
|
|
385
|
+
) -> Type[Any]:
|
|
275
386
|
import typing # lgtm [py/import-and-import-from]
|
|
276
387
|
|
|
388
|
+
if sys.version_info >= (3, 12): # pragma: no cover
|
|
389
|
+
type_alias = (
|
|
390
|
+
type_
|
|
391
|
+
if isinstance(type_, typing.TypeAliasType)
|
|
392
|
+
else typing.get_origin(type_)
|
|
393
|
+
)
|
|
394
|
+
if isinstance(type_alias, typing.TypeAliasType):
|
|
395
|
+
if type_alias_guard is None:
|
|
396
|
+
type_alias_guard = set()
|
|
397
|
+
if id(type_alias) in type_alias_guard:
|
|
398
|
+
raise ValidationError(
|
|
399
|
+
f"Recursive type alias '{type_alias.__name__}' is not supported"
|
|
400
|
+
)
|
|
401
|
+
type_alias_guard = type_alias_guard | {id(type_alias)}
|
|
402
|
+
|
|
403
|
+
type_ = _resolve_type_alias(type_)
|
|
277
404
|
forward = typing.ForwardRef if hasattr(typing, "ForwardRef") else typing._ForwardRef # type: ignore
|
|
278
405
|
if type(type_) is forward:
|
|
279
406
|
return _get_class(module, type_.__forward_arg__)
|
|
280
407
|
elif isinstance(type_, str):
|
|
281
408
|
return _get_class(module, type_)
|
|
409
|
+
elif is_union_annotation(type_):
|
|
410
|
+
is_optional, type_ = _resolve_optional(type_)
|
|
411
|
+
if type_ is Any:
|
|
412
|
+
return Any
|
|
413
|
+
if is_union_annotation(type_):
|
|
414
|
+
args = tuple(
|
|
415
|
+
_resolve_forward(
|
|
416
|
+
arg,
|
|
417
|
+
module=module,
|
|
418
|
+
preserve_container_origin=True,
|
|
419
|
+
type_alias_guard=type_alias_guard,
|
|
420
|
+
)
|
|
421
|
+
for arg in type_.__args__
|
|
422
|
+
)
|
|
423
|
+
type_ = Union[args] # pyrefly: ignore[not-a-type]
|
|
424
|
+
else:
|
|
425
|
+
type_ = _resolve_forward(
|
|
426
|
+
type_,
|
|
427
|
+
module=module,
|
|
428
|
+
preserve_container_origin=True,
|
|
429
|
+
type_alias_guard=type_alias_guard,
|
|
430
|
+
)
|
|
431
|
+
return Optional[type_] if is_optional else type_
|
|
282
432
|
else:
|
|
283
433
|
if is_dict_annotation(type_):
|
|
434
|
+
if preserve_container_origin and (
|
|
435
|
+
type_ in (dict, Dict) or getattr(type_, "__origin__", None) is None
|
|
436
|
+
):
|
|
437
|
+
return type_
|
|
284
438
|
kt, vt = get_dict_key_value_types(type_)
|
|
285
439
|
if kt is not None:
|
|
286
|
-
kt = _resolve_forward(
|
|
440
|
+
kt = _resolve_forward(
|
|
441
|
+
kt,
|
|
442
|
+
module=module,
|
|
443
|
+
preserve_container_origin=preserve_container_origin,
|
|
444
|
+
type_alias_guard=type_alias_guard,
|
|
445
|
+
)
|
|
287
446
|
if vt is not None:
|
|
288
|
-
vt = _resolve_forward(
|
|
447
|
+
vt = _resolve_forward(
|
|
448
|
+
vt,
|
|
449
|
+
module=module,
|
|
450
|
+
preserve_container_origin=preserve_container_origin,
|
|
451
|
+
type_alias_guard=type_alias_guard,
|
|
452
|
+
)
|
|
453
|
+
if preserve_container_origin and isinstance(type_, types.GenericAlias):
|
|
454
|
+
return dict[kt, vt] # type: ignore
|
|
289
455
|
return Dict[kt, vt] # type: ignore
|
|
290
456
|
if is_list_annotation(type_):
|
|
457
|
+
if preserve_container_origin and type_ in (list, List):
|
|
458
|
+
return type_
|
|
291
459
|
et = get_list_element_type(type_)
|
|
292
460
|
if et is not None:
|
|
293
|
-
et = _resolve_forward(
|
|
461
|
+
et = _resolve_forward(
|
|
462
|
+
et,
|
|
463
|
+
module=module,
|
|
464
|
+
preserve_container_origin=preserve_container_origin,
|
|
465
|
+
type_alias_guard=type_alias_guard,
|
|
466
|
+
)
|
|
467
|
+
if preserve_container_origin and isinstance(type_, types.GenericAlias):
|
|
468
|
+
return list[et] # type: ignore
|
|
294
469
|
return List[et] # type: ignore
|
|
295
470
|
if is_tuple_annotation(type_):
|
|
471
|
+
if preserve_container_origin and type_ in (tuple, Tuple):
|
|
472
|
+
return type_
|
|
296
473
|
its = get_tuple_item_types(type_)
|
|
297
|
-
its = tuple(
|
|
474
|
+
its = tuple(
|
|
475
|
+
_resolve_forward(
|
|
476
|
+
it,
|
|
477
|
+
module=module,
|
|
478
|
+
preserve_container_origin=preserve_container_origin,
|
|
479
|
+
type_alias_guard=type_alias_guard,
|
|
480
|
+
)
|
|
481
|
+
for it in its
|
|
482
|
+
)
|
|
483
|
+
if preserve_container_origin and isinstance(type_, types.GenericAlias):
|
|
484
|
+
return tuple[its] # type: ignore
|
|
298
485
|
return Tuple[its] # type: ignore
|
|
299
486
|
|
|
300
487
|
return type_
|
|
@@ -350,7 +537,11 @@ def get_attr_class_fields(obj: Any) -> List["AttrAttribute[Any]"]:
|
|
|
350
537
|
return [f for f in fields if f.metadata.get("omegaconf_ignore") is not True]
|
|
351
538
|
|
|
352
539
|
|
|
353
|
-
def get_attr_data(
|
|
540
|
+
def get_attr_data(
|
|
541
|
+
obj: Any,
|
|
542
|
+
allow_objects: Optional[bool] = None,
|
|
543
|
+
parent: Optional["BaseContainer"] = None,
|
|
544
|
+
) -> Dict[str, Any]:
|
|
354
545
|
from omegaconf.base import Node
|
|
355
546
|
from omegaconf.omegaconf import OmegaConf, _maybe_wrap
|
|
356
547
|
|
|
@@ -363,6 +554,9 @@ def get_attr_data(obj: Any, allow_objects: Optional[bool] = None) -> Dict[str, A
|
|
|
363
554
|
obj_type = obj if is_type else type(obj)
|
|
364
555
|
dummy_parent = OmegaConf.create({}, flags=flags)
|
|
365
556
|
dummy_parent._metadata.object_type = obj_type
|
|
557
|
+
if parent is not None:
|
|
558
|
+
dummy_parent._set_key(parent._key())
|
|
559
|
+
dummy_parent._set_parent(parent._get_parent())
|
|
366
560
|
resolved_hints = get_type_hints(obj_type)
|
|
367
561
|
|
|
368
562
|
for attrib in get_attr_class_fields(obj):
|
|
@@ -393,7 +587,7 @@ def get_attr_data(obj: Any, allow_objects: Optional[bool] = None) -> Dict[str, A
|
|
|
393
587
|
value = copy.deepcopy(value)
|
|
394
588
|
if is_union_annotation(type_) and not is_supported_union_annotation(type_):
|
|
395
589
|
e = ConfigValueError(
|
|
396
|
-
f"
|
|
590
|
+
f"Unsupported type annotation in Union:\n{name}: {type_str(type_)}" # noqa: E231
|
|
397
591
|
)
|
|
398
592
|
format_and_raise(node=None, key=None, value=value, cause=e, msg=str(e))
|
|
399
593
|
|
|
@@ -422,7 +616,9 @@ def get_dataclass_fields(obj: Any) -> List["dataclasses.Field[Any]"]:
|
|
|
422
616
|
|
|
423
617
|
|
|
424
618
|
def get_dataclass_data(
|
|
425
|
-
obj: Any,
|
|
619
|
+
obj: Any,
|
|
620
|
+
allow_objects: Optional[bool] = None,
|
|
621
|
+
parent: Optional["BaseContainer"] = None,
|
|
426
622
|
) -> Dict[str, Any]:
|
|
427
623
|
from omegaconf.base import Node
|
|
428
624
|
from omegaconf.omegaconf import MISSING, OmegaConf, _maybe_wrap
|
|
@@ -433,6 +629,9 @@ def get_dataclass_data(
|
|
|
433
629
|
obj_type = get_type_of(obj)
|
|
434
630
|
dummy_parent = OmegaConf.create({}, flags=flags)
|
|
435
631
|
dummy_parent._metadata.object_type = obj_type
|
|
632
|
+
if parent is not None:
|
|
633
|
+
dummy_parent._set_key(parent._key())
|
|
634
|
+
dummy_parent._set_parent(parent._get_parent())
|
|
436
635
|
resolved_hints = get_type_hints(obj_type)
|
|
437
636
|
for field in get_dataclass_fields(obj):
|
|
438
637
|
name = field.name
|
|
@@ -455,7 +654,7 @@ def get_dataclass_data(
|
|
|
455
654
|
|
|
456
655
|
if is_union_annotation(type_) and not is_supported_union_annotation(type_):
|
|
457
656
|
e = ConfigValueError(
|
|
458
|
-
f"
|
|
657
|
+
f"Unsupported type annotation in Union:\n{name}: {type_str(type_)}" # noqa: E231
|
|
459
658
|
)
|
|
460
659
|
format_and_raise(node=None, key=None, value=value, cause=e, msg=str(e))
|
|
461
660
|
try:
|
|
@@ -552,12 +751,14 @@ def get_structured_config_init_field_aliases(obj: Any) -> Dict[str, str]:
|
|
|
552
751
|
|
|
553
752
|
|
|
554
753
|
def get_structured_config_data(
|
|
555
|
-
obj: Any,
|
|
754
|
+
obj: Any,
|
|
755
|
+
allow_objects: Optional[bool] = None,
|
|
756
|
+
parent: Optional["BaseContainer"] = None,
|
|
556
757
|
) -> Dict[str, Any]:
|
|
557
758
|
if is_dataclass(obj):
|
|
558
|
-
return get_dataclass_data(obj, allow_objects=allow_objects)
|
|
759
|
+
return get_dataclass_data(obj, allow_objects=allow_objects, parent=parent)
|
|
559
760
|
elif is_attr_class(obj):
|
|
560
|
-
return get_attr_data(obj, allow_objects=allow_objects)
|
|
761
|
+
return get_attr_data(obj, allow_objects=allow_objects, parent=parent)
|
|
561
762
|
else:
|
|
562
763
|
raise ValueError(f"Unsupported type: {type(obj).__name__}")
|
|
563
764
|
|
|
@@ -715,21 +916,58 @@ def is_tuple_annotation(type_: Any) -> bool:
|
|
|
715
916
|
|
|
716
917
|
|
|
717
918
|
def is_supported_union_annotation(obj: Any) -> bool:
|
|
718
|
-
"""
|
|
919
|
+
"""Supported value annotations can be used as members of Unions."""
|
|
920
|
+
obj = _resolve_type_alias(obj)
|
|
719
921
|
if not is_union_annotation(obj):
|
|
720
922
|
return False
|
|
721
|
-
|
|
923
|
+
_, obj = _resolve_optional(obj)
|
|
924
|
+
if obj is Any:
|
|
925
|
+
return True
|
|
926
|
+
args = obj.__args__ if is_union_annotation(obj) else (obj,)
|
|
722
927
|
return all(
|
|
723
|
-
is_primitive_type_annotation(arg)
|
|
928
|
+
is_primitive_type_annotation(arg)
|
|
929
|
+
or is_literal_annotation(arg)
|
|
930
|
+
or is_structured_config(arg)
|
|
931
|
+
or is_container_annotation(arg)
|
|
724
932
|
for arg in args
|
|
725
933
|
)
|
|
726
934
|
|
|
727
935
|
|
|
936
|
+
def select_structured_config_union_member(
|
|
937
|
+
value: Any, candidates: List[Any]
|
|
938
|
+
) -> Optional[Any]:
|
|
939
|
+
from omegaconf.dictconfig import DictConfig
|
|
940
|
+
|
|
941
|
+
if isinstance(value, DictConfig):
|
|
942
|
+
value_type = value._metadata.object_type
|
|
943
|
+
elif is_structured_config(value):
|
|
944
|
+
value_type = get_type_of(value)
|
|
945
|
+
else:
|
|
946
|
+
return None
|
|
947
|
+
|
|
948
|
+
if not is_structured_config(value_type):
|
|
949
|
+
return None
|
|
950
|
+
|
|
951
|
+
candidate_set = set(candidates)
|
|
952
|
+
return next(
|
|
953
|
+
(base for base in value_type.__mro__ if base in candidate_set),
|
|
954
|
+
None,
|
|
955
|
+
)
|
|
956
|
+
|
|
957
|
+
|
|
728
958
|
def is_literal_annotation(type_: Any) -> bool:
|
|
729
959
|
origin = getattr(type_, "__origin__", None)
|
|
730
960
|
return origin is Literal
|
|
731
961
|
|
|
732
962
|
|
|
963
|
+
def type_hint_contains_none_literal(type_: Any) -> bool:
|
|
964
|
+
if is_literal_annotation(type_):
|
|
965
|
+
return any(arg is None for arg in type_.__args__)
|
|
966
|
+
return is_union_annotation(type_) and any(
|
|
967
|
+
type_hint_contains_none_literal(arg) for arg in type_.__args__
|
|
968
|
+
)
|
|
969
|
+
|
|
970
|
+
|
|
733
971
|
def is_dict_subclass(type_: Any) -> bool:
|
|
734
972
|
return type_ is not None and isinstance(type_, type) and issubclass(type_, Dict)
|
|
735
973
|
|
|
@@ -744,8 +982,10 @@ def is_primitive_container(obj: Any) -> bool:
|
|
|
744
982
|
|
|
745
983
|
def get_list_element_type(ref_type: Optional[Type[Any]]) -> Any:
|
|
746
984
|
args = getattr(ref_type, "__args__", None)
|
|
747
|
-
if ref_type is not List and args is not None
|
|
985
|
+
if ref_type is not List and args is not None:
|
|
748
986
|
element_type = args[0]
|
|
987
|
+
if element_type is None:
|
|
988
|
+
element_type = NoneType
|
|
749
989
|
else:
|
|
750
990
|
element_type = Any
|
|
751
991
|
return element_type
|
|
@@ -811,6 +1051,8 @@ def get_dict_key_value_types(ref_type: Any) -> Tuple[Any, Any]:
|
|
|
811
1051
|
if args is not None and len(args) == 2:
|
|
812
1052
|
key_type = args[0]
|
|
813
1053
|
element_type = args[1]
|
|
1054
|
+
if element_type is None:
|
|
1055
|
+
element_type = NoneType
|
|
814
1056
|
else:
|
|
815
1057
|
key_type = Any
|
|
816
1058
|
element_type = Any
|
|
@@ -1083,14 +1325,14 @@ def type_str(t: Any, include_module_name: bool = False) -> str:
|
|
|
1083
1325
|
return ret
|
|
1084
1326
|
|
|
1085
1327
|
|
|
1086
|
-
def _ensure_container(target: Any
|
|
1328
|
+
def _ensure_container(target: Any) -> Any:
|
|
1087
1329
|
from omegaconf import OmegaConf
|
|
1088
1330
|
|
|
1089
1331
|
if is_primitive_container(target):
|
|
1090
1332
|
assert isinstance(target, (list, tuple, dict))
|
|
1091
|
-
target = OmegaConf.create(target
|
|
1333
|
+
target = OmegaConf.create(target)
|
|
1092
1334
|
elif is_structured_config(target):
|
|
1093
|
-
target = OmegaConf.structured(target
|
|
1335
|
+
target = OmegaConf.structured(target)
|
|
1094
1336
|
elif not OmegaConf.is_config(target):
|
|
1095
1337
|
raise ValueError(
|
|
1096
1338
|
"Invalid input. Supports one of "
|