omegaconf 2.4.0.dev14__tar.gz → 2.4.0.dev15__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.
Files changed (164) hide show
  1. {omegaconf-2.4.0.dev14/omegaconf.egg-info → omegaconf-2.4.0.dev15}/PKG-INFO +1 -1
  2. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/_impl.py +7 -1
  3. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/basecontainer.py +5 -4
  4. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/dictconfig.py +30 -3
  5. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/grammar_visitor.py +4 -2
  6. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/listconfig.py +1 -3
  7. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/omegaconf.py +15 -3
  8. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/version.py +1 -1
  9. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15/omegaconf.egg-info}/PKG-INFO +1 -1
  10. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/pyproject.toml +1 -1
  11. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/interpolation/test_interpolation.py +54 -1
  12. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_basic_ops_dict.py +50 -6
  13. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_basic_ops_list.py +7 -6
  14. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_merge.py +57 -0
  15. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_omegaconf.py +15 -0
  16. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_select.py +18 -1
  17. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_update.py +17 -1
  18. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/LICENSE +0 -0
  19. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/MANIFEST.in +0 -0
  20. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/README.md +0 -0
  21. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/build_helpers/__init__.py +0 -0
  22. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/build_helpers/bin/antlr-4.11.1-complete.jar +0 -0
  23. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/build_helpers/build_helpers.py +0 -0
  24. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/build_helpers/get_vendored.py +0 -0
  25. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/build_helpers/test_helpers.py +0 -0
  26. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/__init__.py +0 -0
  27. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/_utils.py +0 -0
  28. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/_yaml.py +0 -0
  29. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/base.py +0 -0
  30. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/errors.py +0 -0
  31. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/grammar/OmegaConfGrammarLexer.g4 +0 -0
  32. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/grammar/OmegaConfGrammarParser.g4 +0 -0
  33. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/grammar/__init__.py +0 -0
  34. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/grammar/gen/OmegaConfGrammarLexer.py +0 -0
  35. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/grammar/gen/OmegaConfGrammarParser.py +0 -0
  36. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/grammar/gen/OmegaConfGrammarParserListener.py +0 -0
  37. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/grammar/gen/OmegaConfGrammarParserVisitor.py +0 -0
  38. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/grammar/gen/__init__.py +0 -0
  39. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/grammar_parser.py +0 -0
  40. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/nodes.py +0 -0
  41. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/py.typed +0 -0
  42. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/resolvers/__init__.py +0 -0
  43. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/resolvers/oc/__init__.py +0 -0
  44. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/resolvers/oc/dict.py +0 -0
  45. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/tupleconfig.py +0 -0
  46. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/typing.py +0 -0
  47. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/__init__.py +0 -0
  48. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/BufferedTokenStream.py +0 -0
  49. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/CommonTokenFactory.py +0 -0
  50. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/CommonTokenStream.py +0 -0
  51. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/FileStream.py +0 -0
  52. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/InputStream.py +0 -0
  53. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/IntervalSet.py +0 -0
  54. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/LL1Analyzer.py +0 -0
  55. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/Lexer.py +0 -0
  56. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/ListTokenSource.py +0 -0
  57. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/Parser.py +0 -0
  58. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/ParserInterpreter.py +0 -0
  59. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/ParserRuleContext.py +0 -0
  60. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/PredictionContext.py +0 -0
  61. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/Recognizer.py +0 -0
  62. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/RuleContext.py +0 -0
  63. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/StdinStream.py +0 -0
  64. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/Token.py +0 -0
  65. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/TokenStreamRewriter.py +0 -0
  66. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/Utils.py +0 -0
  67. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/__init__.py +0 -0
  68. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/_pygrun.py +0 -0
  69. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/ATN.py +0 -0
  70. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/ATNConfig.py +0 -0
  71. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/ATNConfigSet.py +0 -0
  72. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/ATNDeserializationOptions.py +0 -0
  73. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/ATNDeserializer.py +0 -0
  74. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/ATNSimulator.py +0 -0
  75. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/ATNState.py +0 -0
  76. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/ATNType.py +0 -0
  77. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/LexerATNSimulator.py +0 -0
  78. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/LexerAction.py +0 -0
  79. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/LexerActionExecutor.py +0 -0
  80. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/ParserATNSimulator.py +0 -0
  81. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/PredictionMode.py +0 -0
  82. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/SemanticContext.py +0 -0
  83. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/Transition.py +0 -0
  84. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/atn/__init__.py +0 -0
  85. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/dfa/DFA.py +0 -0
  86. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/dfa/DFASerializer.py +0 -0
  87. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/dfa/DFAState.py +0 -0
  88. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/dfa/__init__.py +0 -0
  89. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/error/DiagnosticErrorListener.py +0 -0
  90. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/error/ErrorListener.py +0 -0
  91. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/error/ErrorStrategy.py +0 -0
  92. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/error/Errors.py +0 -0
  93. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/error/__init__.py +0 -0
  94. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/tree/Chunk.py +0 -0
  95. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/tree/ParseTreeMatch.py +0 -0
  96. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/tree/ParseTreePattern.py +0 -0
  97. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/tree/ParseTreePatternMatcher.py +0 -0
  98. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/tree/RuleTagToken.py +0 -0
  99. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/tree/TokenTagToken.py +0 -0
  100. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/tree/Tree.py +0 -0
  101. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/tree/Trees.py +0 -0
  102. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/tree/__init__.py +0 -0
  103. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/xpath/XPath.py +0 -0
  104. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/xpath/XPathLexer.py +0 -0
  105. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf/vendor/antlr4/xpath/__init__.py +0 -0
  106. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf.egg-info/SOURCES.txt +0 -0
  107. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf.egg-info/dependency_links.txt +0 -0
  108. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf.egg-info/requires.txt +0 -0
  109. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/omegaconf.egg-info/top_level.txt +0 -0
  110. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/requirements/base.txt +0 -0
  111. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/requirements/dev.txt +0 -0
  112. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/requirements/docs.txt +0 -0
  113. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/setup.cfg +0 -0
  114. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/setup.py +0 -0
  115. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/__init__.py +0 -0
  116. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/conftest.py +0 -0
  117. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/data/2.0.6.pickle +0 -0
  118. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/data/2.1.0.rc1.pickle +0 -0
  119. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/data/load.py +0 -0
  120. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/data/save.py +0 -0
  121. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/examples/__init__.py +0 -0
  122. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/examples/dataclass_postponed_annotations.py +0 -0
  123. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/examples/test_dataclass_example.py +0 -0
  124. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/examples/test_postponed_annotations.py +0 -0
  125. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/interpolation/__init__.py +0 -0
  126. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/interpolation/built_in_resolvers/__init__.py +0 -0
  127. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/interpolation/built_in_resolvers/test_oc_create.py +0 -0
  128. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/interpolation/built_in_resolvers/test_oc_decode.py +0 -0
  129. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/interpolation/built_in_resolvers/test_oc_deprecated.py +0 -0
  130. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/interpolation/built_in_resolvers/test_oc_dict.py +0 -0
  131. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/interpolation/built_in_resolvers/test_oc_env.py +0 -0
  132. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/interpolation/built_in_resolvers/test_oc_select.py +0 -0
  133. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/interpolation/test_custom_resolvers.py +0 -0
  134. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/interpolation/test_resolver_annotation_validation.py +0 -0
  135. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/structured_conf/__init__.py +0 -0
  136. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/structured_conf/data/__init__.py +0 -0
  137. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/structured_conf/data/attr_classes.py +0 -0
  138. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/structured_conf/data/dataclasses.py +0 -0
  139. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/structured_conf/data/dataclasses_pre_311.py +0 -0
  140. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/structured_conf/test_structured_basic.py +0 -0
  141. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/structured_conf/test_structured_config.py +0 -0
  142. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_base_config.py +0 -0
  143. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_basic_ops_tuple.py +0 -0
  144. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_compare_dictconfig_vs_dict.py +0 -0
  145. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_config_eq.py +0 -0
  146. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_container_unions.py +0 -0
  147. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_create.py +0 -0
  148. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_errors.py +0 -0
  149. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_get_full_key.py +0 -0
  150. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_grammar.py +0 -0
  151. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_matrix.py +0 -0
  152. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_nested_containers.py +0 -0
  153. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_nodes.py +0 -0
  154. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_readonly.py +0 -0
  155. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_serialization.py +0 -0
  156. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_struct.py +0 -0
  157. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_structured_config_unions.py +0 -0
  158. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_to_container.py +0 -0
  159. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_to_yaml.py +0 -0
  160. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_tuple_integration.py +0 -0
  161. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_tuple_merge.py +0 -0
  162. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_tuple_structured.py +0 -0
  163. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/tests/test_unions.py +0 -0
  164. {omegaconf-2.4.0.dev14 → omegaconf-2.4.0.dev15}/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.dev14
3
+ Version: 2.4.0.dev15
4
4
  Summary: A flexible configuration library
5
5
  Home-page: https://github.com/omry/omegaconf
6
6
  Author: Omry Yadan
@@ -22,7 +22,13 @@ def _resolve_container_value(cfg: Container, key: Any) -> None:
22
22
  node = cfg._get_child(key)
23
23
  assert isinstance(node, Node)
24
24
  if node._is_interpolation():
25
- resolved = node._dereference_node()
25
+ try:
26
+ resolved = node._dereference_node()
27
+ except Exception as e:
28
+ # Attach the same key/object_type context that direct node access
29
+ # reports, so errors surfaced through OmegaConf.resolve() stay
30
+ # diagnosable.
31
+ cfg._format_and_raise(key=key, value=None, cause=e)
26
32
  if isinstance(resolved, Container):
27
33
  _resolve(resolved)
28
34
  if isinstance(resolved, InterpolationResultNode):
@@ -417,16 +417,17 @@ class BaseContainer(Container, ABC):
417
417
  ref_type=src_ref_type, object_type=src_type
418
418
  )
419
419
 
420
- if dest._is_interpolation() and src_was_missing_structured:
421
- # Keep unresolved structured interpolations intact when the source
422
- # was originally MISSING; the synthesized prototype only exists to
423
- # preserve type information during merge.
420
+ if (dest._is_interpolation() or dest._is_none()) and src_was_missing_structured:
421
+ # Keep unresolved structured interpolations and null values intact
422
+ # when the source was originally MISSING; the synthesized prototype
423
+ # only exists to preserve type information during merge.
424
424
  _update_types(node=dest, ref_type=src_ref_type, object_type=src_type)
425
425
  return
426
426
 
427
427
  if (
428
428
  (dest._is_interpolation() and not src_was_missing_structured)
429
429
  or dest._is_missing()
430
+ or dest._is_none()
430
431
  ) and not src._is_missing():
431
432
  expand(dest)
432
433
 
@@ -34,6 +34,7 @@ from ._utils import (
34
34
  get_value_kind,
35
35
  is_container_annotation,
36
36
  is_dict,
37
+ is_int,
37
38
  is_primitive_dict,
38
39
  is_structured_config,
39
40
  is_structured_config_frozen,
@@ -69,6 +70,7 @@ def _make_key_suggestion(key: Any, available: Iterable) -> str:
69
70
  class DictConfig(BaseContainer, MutableMapping[Any, Any]):
70
71
  _metadata: ContainerMetadata
71
72
  _content: Union[Dict[DictKeyType, Node], None, str]
73
+ __hash__ = None # type: ignore[assignment]
72
74
 
73
75
  def __init__(
74
76
  self,
@@ -227,6 +229,8 @@ class DictConfig(BaseContainer, MutableMapping[Any, Any]):
227
229
  self._validate_non_optional(None, src)
228
230
 
229
231
  dest_obj_type = OmegaConf.get_type(dest)
232
+ if dest._is_none() and is_structured_config(dest._metadata.ref_type):
233
+ dest_obj_type = dest._metadata.ref_type
230
234
  src_obj_type = OmegaConf.get_type(src)
231
235
 
232
236
  if dest._is_missing() and src._metadata.object_type not in (dict, None):
@@ -334,8 +338,34 @@ class DictConfig(BaseContainer, MutableMapping[Any, Any]):
334
338
 
335
339
  def __set_impl(self, key: DictKeyType, value: Any) -> None:
336
340
  key = self._validate_and_normalize_key(key)
341
+ self._validate_non_ambiguous_key(key)
337
342
  self._set_item_impl(key, value)
338
343
 
344
+ def _validate_non_ambiguous_key(self, key: DictKeyType) -> None:
345
+ content = self.__dict__["_content"]
346
+ if self._metadata.key_type is not Any or not isinstance(content, dict):
347
+ return
348
+
349
+ conflicting_key: Optional[DictKeyType] = None
350
+ if isinstance(key, str) and is_int(key):
351
+ numeric_key = int(key)
352
+ node = content.get(numeric_key)
353
+ if (
354
+ str(numeric_key) == key
355
+ and isinstance(node, Node)
356
+ and type(node._key()) is int
357
+ ):
358
+ conflicting_key = numeric_key
359
+ elif type(key) is int and str(key) in content:
360
+ node = content.get(key)
361
+ if not isinstance(node, Node) or type(node._key()) is int:
362
+ conflicting_key = str(key)
363
+
364
+ if conflicting_key is not None:
365
+ raise KeyValidationError(
366
+ f"Conflicting integer and string keys: {conflicting_key!r} and {key!r}"
367
+ )
368
+
339
369
  # hide content while inspecting in debugger
340
370
  def __dir__(self) -> Iterable[str]:
341
371
  if self._is_missing() or self._is_none():
@@ -634,9 +664,6 @@ class DictConfig(BaseContainer, MutableMapping[Any, Any]):
634
664
  return not x
635
665
  return NotImplemented
636
666
 
637
- def __hash__(self) -> int:
638
- return hash(str(self))
639
-
640
667
  def _promote(self, type_or_prototype: Optional[Type[Any]]) -> None:
641
668
  """
642
669
  Retypes a node.
@@ -86,10 +86,12 @@ class GrammarVisitor(OmegaConfGrammarParserVisitor):
86
86
  if isinstance(child, OmegaConfGrammarParser.InterpolationContext):
87
87
  child_text = child.getText()
88
88
  res = _get_value(self.visitInterpolation(child))
89
- if not isinstance(res, str):
89
+ if type(res) is int:
90
+ return str(res)
91
+ elif not isinstance(res, str):
90
92
  raise InterpolationResolutionError(
91
93
  f"The following interpolation is used to denote a config key and "
92
- f"thus should return a string, but instead returned `{res}` of "
94
+ f"thus should return a string or integer, but instead returned `{res}` of "
93
95
  f"type `{type(res)}`: {child_text}"
94
96
  )
95
97
  return res
@@ -47,6 +47,7 @@ from .errors import (
47
47
 
48
48
  class ListConfig(BaseContainer, MutableSequence[Any]):
49
49
  _content: Union[List[Node], None, str]
50
+ __hash__ = None # type: ignore[assignment]
50
51
 
51
52
  def __init__(
52
53
  self,
@@ -523,9 +524,6 @@ class ListConfig(BaseContainer, MutableSequence[Any]):
523
524
  return not x
524
525
  return NotImplemented
525
526
 
526
- def __hash__(self) -> int:
527
- return hash(str(self))
528
-
529
527
  def __iter__(self) -> Iterator[Any]:
530
528
  return self._iter_ex(resolve=True)
531
529
 
@@ -1423,7 +1423,9 @@ class OmegaConf:
1423
1423
  )
1424
1424
 
1425
1425
  last_key: Union[str, int] = last
1426
- if OmegaConf.is_sequence(root):
1426
+ if OmegaConf.is_dict(root):
1427
+ _, last_key = _select_one(root, last, throw_on_missing=False)
1428
+ elif OmegaConf.is_sequence(root):
1427
1429
  last_key = int(last)
1428
1430
 
1429
1431
  ctx = flag_override(root, "struct", False) if force_add else nullcontext()
@@ -1438,8 +1440,10 @@ class OmegaConf:
1438
1440
  return
1439
1441
 
1440
1442
  if OmegaConf.is_dict(root):
1441
- assert isinstance(last_key, str)
1442
- root.__setattr__(last_key, value)
1443
+ if isinstance(last_key, int):
1444
+ root.__setitem__(last_key, value)
1445
+ else:
1446
+ root.__setattr__(last_key, value)
1443
1447
  elif OmegaConf.is_sequence(root):
1444
1448
  assert isinstance(last_key, int)
1445
1449
  root.__setitem__(last_key, value)
@@ -1973,6 +1977,14 @@ def _select_one(
1973
1977
  if isinstance(c, DictConfig):
1974
1978
  assert isinstance(ret_key, str)
1975
1979
  val = c._get_child(ret_key, validate_access=False)
1980
+ if val is None and is_int(ret_key):
1981
+ numeric_key = int(ret_key)
1982
+ raw_node = c._get_node(numeric_key, validate_access=False)
1983
+ if isinstance(raw_node, Node) and type(raw_node._key()) is int:
1984
+ val = c._get_child(numeric_key, validate_access=False)
1985
+ ret_key = numeric_key
1986
+ else:
1987
+ val = None
1976
1988
  elif isinstance(c, (ListConfig, TupleConfig)):
1977
1989
  assert isinstance(ret_key, str)
1978
1990
  if not is_int(ret_key):
@@ -1,7 +1,7 @@
1
1
  import sys # pragma: no cover
2
2
 
3
3
  # Managed by bump-my-version; see pyproject.toml for bump commands.
4
- __version__ = "2.4.0.dev14"
4
+ __version__ = "2.4.0.dev15"
5
5
 
6
6
  msg = """OmegaConf 2.4 and above is compatible with Python 3.10 and newer.
7
7
  You have the following options:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omegaconf
3
- Version: 2.4.0.dev14
3
+ Version: 2.4.0.dev15
4
4
  Summary: A flexible configuration library
5
5
  Home-page: https://github.com/omry/omegaconf
6
6
  Author: Omry Yadan
@@ -29,7 +29,7 @@ norecursedirs = ["subprojects", ".git", ".sl", ".venv"]
29
29
  # Version source of truth. Use bump-my-version so configured files stay in sync.
30
30
  # `bump-my-version bump pre_n` updates 2.4.0.dev13 to 2.4.0.dev14.
31
31
  # `bump-my-version bump --new-version 2.4.0` sets the final release version.
32
- current_version = "2.4.0.dev14"
32
+ current_version = "2.4.0.dev15"
33
33
  parse = '''(?x)
34
34
  (?P<major>\d+)
35
35
  \.(?P<minor>\d+)
@@ -2,7 +2,7 @@ import copy
2
2
  import re
3
3
  from pathlib import Path
4
4
  from textwrap import dedent
5
- from typing import Any, Tuple
5
+ from typing import Any, Tuple, Union
6
6
 
7
7
  from pytest import mark, param, raises
8
8
 
@@ -214,6 +214,59 @@ def test_interpolation_after_copy(copy_func: Any, data: Any, key: Any) -> None:
214
214
  assert copy_func(dict_cfg._get_node(key))._dereference_node() == 10
215
215
 
216
216
 
217
+ @mark.parametrize("key", [param(1, id="int"), param("1", id="str")])
218
+ def test_interpolation_to_integer_key(key: Any) -> None:
219
+ cfg = OmegaConf.create({key: "value", "ref": "${1}"})
220
+
221
+ assert cfg.ref == "value"
222
+
223
+
224
+ @mark.parametrize("resolution", [param(224, id="int"), param("224", id="str")])
225
+ def test_interpolation_with_nested_integer_key(resolution: Any) -> None:
226
+ cfg = OmegaConf.create(
227
+ {
228
+ "anchors": {"imagenet": {resolution: {"data": "value"}}},
229
+ "dataset": "imagenet",
230
+ "resolution": 224,
231
+ "ref": "${anchors.${dataset}.${resolution}.data}",
232
+ }
233
+ )
234
+
235
+ assert cfg.ref == "value"
236
+
237
+
238
+ def test_interpolation_with_nested_integer_key_from_yaml() -> None:
239
+ cfg = OmegaConf.create(
240
+ dedent(
241
+ """
242
+ anchors:
243
+ coco2014:
244
+ 224:
245
+ data: [1, 2, 3]
246
+ dataset: coco2014
247
+ resolution: 224
248
+ ref: ${anchors.${dataset}.${resolution}.data}
249
+ """
250
+ )
251
+ )
252
+
253
+ assert cfg.ref == [1, 2, 3]
254
+
255
+
256
+ def test_interpolation_to_typed_integer_key() -> None:
257
+ values = DictConfig({1: "value"}, key_type=int)
258
+ cfg = OmegaConf.create({"values": values, "ref": "${values.1}"})
259
+
260
+ assert cfg.ref == "value"
261
+
262
+
263
+ def test_interpolation_to_union_typed_integer_key() -> None:
264
+ values = DictConfig({1: 10}, element_type=Union[int, str])
265
+ cfg = OmegaConf.create({"values": values, "ref": "${values.1}"})
266
+
267
+ assert cfg.ref == 10
268
+
269
+
217
270
  def test_resolve_interpolation_without_parent() -> None:
218
271
  with raises(
219
272
  IRE, match=re.escape("Cannot resolve interpolation for a node without a parent")
@@ -871,12 +871,13 @@ def test_dir(cfg: Any, key: Any, expected: Any) -> None:
871
871
  assert dir(c._get_node(key)) == expected
872
872
 
873
873
 
874
- def test_hash() -> None:
875
- c1 = OmegaConf.create({"a": 10})
876
- c2 = OmegaConf.create({"a": 10})
877
- assert hash(c1) == hash(c2)
878
- c2.a = 20
879
- assert hash(c1) != hash(c2)
874
+ def test_unhashable() -> None:
875
+ cfg = OmegaConf.create({"a": 10})
876
+ with raises(TypeError, match="unhashable"):
877
+ hash(cfg)
878
+ OmegaConf.set_readonly(cfg, True)
879
+ with raises(TypeError, match="unhashable"):
880
+ hash(cfg)
880
881
 
881
882
 
882
883
  @mark.parametrize("default", ["default", 0, None])
@@ -988,6 +989,49 @@ def test_creation_with_invalid_key() -> None:
988
989
  OmegaConf.create({object(): "a"})
989
990
 
990
991
 
992
+ @mark.parametrize(
993
+ "items",
994
+ [
995
+ param([(1, "numeric"), ("1", "string")], id="int-first"),
996
+ param([("1", "string"), (1, "numeric")], id="str-first"),
997
+ ],
998
+ )
999
+ def test_creation_with_ambiguous_integer_key(items: Any) -> None:
1000
+ with raises(KeyValidationError, match="integer and string keys"):
1001
+ OmegaConf.create(dict(items))
1002
+
1003
+
1004
+ @mark.parametrize(
1005
+ ("initial_key", "new_key"),
1006
+ [param(1, "1", id="int-first"), param("1", 1, id="str-first")],
1007
+ )
1008
+ def test_setitem_with_ambiguous_integer_key(initial_key: Any, new_key: Any) -> None:
1009
+ cfg = OmegaConf.create({initial_key: "initial"})
1010
+
1011
+ with raises(KeyValidationError, match="integer and string keys"):
1012
+ cfg[new_key] = "new"
1013
+
1014
+
1015
+ def test_float_and_string_keys_are_not_ambiguous() -> None:
1016
+ cfg = OmegaConf.create({1.5: "float", "1.5": "string"})
1017
+
1018
+ assert cfg[1.5] == "float"
1019
+ assert cfg["1.5"] == "string"
1020
+
1021
+
1022
+ @mark.parametrize("stored_key", [param(True, id="bool"), param(1.0, id="float")])
1023
+ def test_setitem_integer_key_updates_equal_non_integer_key(stored_key: Any) -> None:
1024
+ cfg = OmegaConf.create({stored_key: "initial", "1": "string"})
1025
+
1026
+ cfg[1] = "updated"
1027
+
1028
+ assert cfg[stored_key] == "updated"
1029
+ assert cfg["1"] == "string"
1030
+ node = cfg._get_node(stored_key)
1031
+ assert node is not None
1032
+ assert type(node._key()) is type(stored_key)
1033
+
1034
+
991
1035
  def test_setitem_with_invalid_key() -> None:
992
1036
  cfg = OmegaConf.create()
993
1037
  with raises(KeyValidationError):
@@ -858,12 +858,13 @@ def test_append_throws_not_changing_list() -> None:
858
858
  assert c == [iv]
859
859
 
860
860
 
861
- def test_hash() -> None:
862
- c1 = OmegaConf.create([10])
863
- c2 = OmegaConf.create([10])
864
- assert hash(c1) == hash(c2)
865
- c2[0] = 20
866
- assert hash(c1) != hash(c2)
861
+ def test_unhashable() -> None:
862
+ cfg = OmegaConf.create([10])
863
+ with raises(TypeError, match="unhashable"):
864
+ hash(cfg)
865
+ OmegaConf.set_readonly(cfg, True)
866
+ with raises(TypeError, match="unhashable"):
867
+ hash(cfg)
867
868
 
868
869
 
869
870
  @mark.parametrize(
@@ -459,6 +459,63 @@ def test_merge(
459
459
  merge_function(*configs)
460
460
 
461
461
 
462
+ @mark.parametrize("merge", [OmegaConf.merge, OmegaConf.unsafe_merge])
463
+ @mark.parametrize(
464
+ ("override", "expected_count"),
465
+ [param({}, 10, id="empty"), param({"count": 20}, 20, id="non-empty")],
466
+ )
467
+ def test_merge_none_structured_config_root(
468
+ merge: Any, override: Dict[str, Any], expected_count: int
469
+ ) -> None:
470
+ class RuntimeObject: ...
471
+
472
+ @dataclass
473
+ class Value:
474
+ count: int = 10
475
+ inherited: int = "${..template}" # type: ignore[assignment]
476
+ payload: Any = field(default_factory=RuntimeObject)
477
+
478
+ @dataclass
479
+ class Config:
480
+ template: int = 30
481
+ value: Optional[Value] = None
482
+
483
+ cfg = OmegaConf.structured(Config, flags={"allow_objects": True})
484
+ value = cfg._get_node("value")
485
+
486
+ result = merge(value, override)
487
+
488
+ assert OmegaConf.get_type(result) is Value
489
+ assert result.count == expected_count
490
+ assert result.inherited == 30
491
+ assert isinstance(result.payload, RuntimeObject)
492
+ assert result._get_flag("allow_objects") is True
493
+ assert result._key() == "value"
494
+
495
+
496
+ def test_merge_none_structured_config_root_rejects_incompatible_type() -> None:
497
+ destination = OmegaConf.structured(C)._get_node("x")
498
+ source = OmegaConf.structured(B)
499
+
500
+ with raises(ValidationError):
501
+ OmegaConf.merge(destination, source)
502
+
503
+
504
+ def test_merge_missing_structured_config_into_none_root() -> None:
505
+ destination = OmegaConf.structured(C)._get_node("x")
506
+ source = OmegaConf.structured(B)._get_node("x")
507
+
508
+ result = OmegaConf.merge(destination, source)
509
+
510
+ assert result._is_none()
511
+
512
+
513
+ def test_merge_none_dictconfig_root() -> None:
514
+ result = OmegaConf.merge(DictConfig(None), {"key": "value"})
515
+
516
+ assert result == {"key": "value"}
517
+
518
+
462
519
  def test_merge_missing_structured_keeps_interpolation_target() -> None:
463
520
  @dataclass
464
521
  class Defaults:
@@ -572,6 +572,21 @@ def test_resolve_raises_on_resolver_arg_to_missing(restore_resolvers: Any) -> No
572
572
  OmegaConf.resolve(cfg)
573
573
 
574
574
 
575
+ def test_resolve_error_keeps_key_and_object_type() -> None:
576
+ """https://github.com/omry/omegaconf/issues/1330"""
577
+ cfg = OmegaConf.structured(StructuredWithMissing)
578
+ cfg.num = "${no_such_key}"
579
+
580
+ with raises(InterpolationKeyError) as direct:
581
+ cfg.num
582
+ with raises(InterpolationKeyError) as resolved:
583
+ OmegaConf.resolve(cfg)
584
+
585
+ assert resolved.value.full_key == direct.value.full_key == "num"
586
+ assert direct.value.object_type is StructuredWithMissing
587
+ assert resolved.value.object_type is StructuredWithMissing
588
+
589
+
575
590
  def test_resolve_does_not_raise_when_resolver_returns_dict_config(
576
591
  restore_resolvers: Any,
577
592
  ) -> None:
@@ -1,5 +1,5 @@
1
1
  from contextlib import AbstractContextManager
2
- from typing import Any, Optional
2
+ from typing import Any, Optional, Union
3
3
 
4
4
  from pytest import mark, param, raises, warns
5
5
 
@@ -7,6 +7,7 @@ from omegaconf import DictConfig, ListConfig, MissingMandatoryValue, OmegaConf
7
7
  from omegaconf._impl import select_value
8
8
  from omegaconf._utils import _ensure_container
9
9
  from omegaconf.errors import InterpolationKeyError
10
+ from tests import Color
10
11
 
11
12
 
12
13
  def _register_resolver(register_func: Any, name: str, resolver: Any) -> None:
@@ -35,6 +36,16 @@ class TestSelect:
35
36
  param({"a": ListConfig(None)}, "a.b", None, id="dict:nesting_into_none"),
36
37
  # value returned
37
38
  param({"c": 1}, "c", 1, id="dict:int"),
39
+ param({1: "one"}, "1", "one", id="dict:integer-key"),
40
+ param(
41
+ DictConfig({1: 10}, element_type=Union[int, str]),
42
+ "1",
43
+ 10,
44
+ id="dict:union-typed-integer-key",
45
+ ),
46
+ param({True: "bool"}, "1", None, id="dict:bool-key-not-coerced"),
47
+ param({1.5: "float"}, r"1\.5", None, id="dict:float-key-not-coerced"),
48
+ param({Color.RED: "red"}, "RED", None, id="dict:enum-key-not-coerced"),
38
49
  param({"a": {"v": 1}}, "a.v", 1, id="dict:int"),
39
50
  param({"a": {"v": 1}}, "a", {"v": 1}, id="dict:dict"),
40
51
  param({"missing": "???"}, "missing", None, id="dict:missing"),
@@ -88,6 +99,12 @@ class TestSelect:
88
99
  else:
89
100
  assert OmegaConf.select(cfg, key) == expected
90
101
 
102
+ def test_can_select_integer_key(self, struct: Optional[bool]) -> None:
103
+ cfg = _ensure_container({1: "one"})
104
+ OmegaConf.set_struct(cfg, struct)
105
+
106
+ assert OmegaConf.can_select(cfg, "1")
107
+
91
108
  @mark.parametrize(
92
109
  "register_func",
93
110
  [OmegaConf.legacy_register_resolver, OmegaConf.register_resolver],
@@ -1,4 +1,4 @@
1
- from typing import Any
1
+ from typing import Any, Union
2
2
 
3
3
  from pytest import mark, param, raises
4
4
 
@@ -18,6 +18,7 @@ from tests import Group, Package, User
18
18
  [
19
19
  # dict
20
20
  param({"a": "b"}, "a", "c", {"a": "c"}, id="replace:string"),
21
+ param({1: "old"}, "1", "new", {1: "new"}, id="replace:integer-key"),
21
22
  param({"a": "b"}, "c", "d", {"a": "b", "c": "d"}, id="add:string"),
22
23
  param({"a": "b"}, "c", None, {"a": "b", "c": None}, id="none_value"),
23
24
  param({}, "a", {}, {"a": {}}, id="dict:value:empty_dict"),
@@ -56,6 +57,13 @@ from tests import Group, Package, User
56
57
  {"a": {"b": 1, "c": 2}},
57
58
  id="dict_value:merge",
58
59
  ),
60
+ param(
61
+ {1: {"a": 1}},
62
+ "1",
63
+ {"b": 2},
64
+ {1: {"a": 1, "b": 2}},
65
+ id="dict_value:integer-key:merge",
66
+ ),
59
67
  # list
60
68
  param({"a": [1, 2]}, "a", [2, 3], {"a": [2, 3]}, id="list:replace"),
61
69
  param([1, 2, 3], "1", "abc", [1, "abc", 3], id="list:update"),
@@ -193,6 +201,14 @@ def test_update_list_index_error() -> None:
193
201
  assert c == [1, 2, 3]
194
202
 
195
203
 
204
+ def test_update_union_typed_integer_key() -> None:
205
+ cfg = DictConfig({1: 10}, element_type=Union[int, str])
206
+
207
+ OmegaConf.update(cfg, "1", 20)
208
+
209
+ assert cfg == {1: 20}
210
+
211
+
196
212
  def test_update_merge_by_default() -> None:
197
213
  cfg = OmegaConf.create({"a": {"b": 10}})
198
214
  OmegaConf.update(cfg, "a", {"c": 20})
File without changes