nodes: 0, module; 1, function_definition; 2, function_name:merged_packages; 3, parameters; 4, block; 5, identifier:env_packages; 6, identifier:names; 7, expression_statement; 8, expression_statement; 9, expression_statement; 10, expression_statement; 11, for_statement; 12, if_statement; 13, return_statement; 14, comment:"""
      Return union set of environment packages with given names
  
      >>> sorted(merged_packages(
      ...     {
      ...         'a': {'x': 1, 'y': 2},
      ...         'b': {'y': 2, 'z': 3},
      ...         'c': {'z': 3, 'w': 4}
      ...     },
      ...     ['a', 'b']
      ... ).items())
      [('x', 1), ('y', 2), ('z', 3)]
      """; 15, assignment; 16, assignment; 17, assignment; 18, pattern_list; 19, identifier:combined_packages; 20, block; 21, identifier:errors; 22, block; 23, identifier:result; 24, identifier:combined_packages; 25, call; 26, identifier:result; 27, dictionary; 28, identifier:errors; 29, call; 30, identifier:name; 31, identifier:version; 32, if_statement; 33, for_statement; 34, raise_statement; 35, identifier:sorted; 36, argument_list; 37, identifier:set; 38, argument_list; 39, comparison_operator:name in result; 40, block; 41, else_clause; 42, identifier:error; 43, call; 44, block; 45, call; 46, call; 47, identifier:name; 48, identifier:result; 49, if_statement; 50, block; 51, identifier:sorted; 52, argument_list; 53, expression_statement; 54, identifier:RuntimeError; 55, argument_list; 56, attribute; 57, generator_expression; 58, comparison_operator:result[name] != version; 59, block; 60, expression_statement; 61, identifier:errors; 62, call; 63, string:"Please add constraints for the package version listed above"; 64, attribute; 65, identifier:from_iterable; 66, call; 67, for_in_clause; 68, subscript; 69, identifier:version; 70, expression_statement; 71, assignment; 72, attribute; 73, argument_list; 74, identifier:itertools; 75, identifier:chain; 76, attribute; 77, argument_list; 78, identifier:name; 79, identifier:names; 80, identifier:result; 81, identifier:name; 82, call; 83, subscript; 84, identifier:version; 85, identifier:logger; 86, identifier:error; 87, concatenated_string; 88, subscript; 89, subscript; 90, subscript; 91, subscript; 92, identifier:items; 93, attribute; 94, argument_list; 95, identifier:result; 96, identifier:name; 97, string:"Package %s was resolved to different "; 98, string:"versions in different environments: %s and %s"; 99, identifier:error; 100, integer:0; 101, identifier:error; 102, integer:1; 103, identifier:error; 104, integer:2; 105, identifier:env_packages; 106, identifier:name; 107, identifier:errors; 108, identifier:add; 109, tuple; 110, identifier:name; 111, identifier:version; 112, subscript; 113, identifier:result; 114, identifier:name
code: def merged_packages(env_packages, names):
      """
      Return union set of environment packages with given names
  
      >>> sorted(merged_packages(
      ...     {
      ...         'a': {'x': 1, 'y': 2},
      ...         'b': {'y': 2, 'z': 3},
      ...         'c': {'z': 3, 'w': 4}
      ...     },
      ...     ['a', 'b']
      ... ).items())
      [('x', 1), ('y', 2), ('z', 3)]
      """
      combined_packages = sorted(itertools.chain.from_iterable(
          env_packages[name].items()
          for name in names
      ))
      result = {}
      errors = set()
      for name, version in combined_packages:
          if name in result:
              if result[name] != version:
                  errors.add((name, version, result[name]))
          else:
              result[name] = version
      if errors:
          for error in sorted(errors):
              logger.error(
                  "Package %s was resolved to different "
                  "versions in different environments: %s and %s",
                  error[0], error[1], error[2],
              )
          raise RuntimeError(
              "Please add constraints for the package version listed above"
          )
      return result