code: def determine_modules_to_test(changed_modules, deduplicated=True):
      """
      Given a set of modules that have changed, compute the transitive closure of those modules'
      dependent modules in order to determine the set of modules that should be tested.
  
      Returns a topologically-sorted list of modules (ties are broken by sorting on module names).
      If ``deduplicated`` is disabled, the modules are returned without tacking the deduplication
      by dependencies into account.
  
      >>> [x.name for x in determine_modules_to_test([modules.root])]
      ['root']
      >>> [x.name for x in determine_modules_to_test([modules.build])]
      ['root']
      >>> [x.name for x in determine_modules_to_test([modules.core])]
      ['root']
      >>> [x.name for x in determine_modules_to_test([modules.launcher])]
      ['root']
      >>> [x.name for x in determine_modules_to_test([modules.graphx])]
      ['graphx', 'examples']
      >>> sorted([x.name for x in determine_modules_to_test([modules.sql])])
      ... # doctest: +NORMALIZE_WHITESPACE
      ['avro', 'connect', 'docker-integration-tests', 'examples', 'hive', 'hive-thriftserver',
       'mllib', 'protobuf', 'pyspark-connect', 'pyspark-ml', 'pyspark-ml-connect', 'pyspark-mllib',
       'pyspark-pandas', 'pyspark-pandas-connect-part0', 'pyspark-pandas-connect-part1',
       'pyspark-pandas-connect-part2', 'pyspark-pandas-connect-part3', 'pyspark-pandas-slow',
       'pyspark-sql', 'pyspark-testing', 'repl', 'sparkr', 'sql', 'sql-kafka-0-10']
      >>> sorted([x.name for x in determine_modules_to_test(
      ...     [modules.sparkr, modules.sql], deduplicated=False)])
      ... # doctest: +NORMALIZE_WHITESPACE
      ['avro', 'connect', 'docker-integration-tests', 'examples', 'hive', 'hive-thriftserver',
       'mllib', 'protobuf', 'pyspark-connect', 'pyspark-ml', 'pyspark-ml-connect', 'pyspark-mllib',
       'pyspark-pandas', 'pyspark-pandas-connect-part0', 'pyspark-pandas-connect-part1',
       'pyspark-pandas-connect-part2', 'pyspark-pandas-connect-part3', 'pyspark-pandas-slow',
       'pyspark-sql', 'pyspark-testing', 'repl', 'sparkr', 'sql', 'sql-kafka-0-10']
      >>> sorted([x.name for x in determine_modules_to_test(
      ...     [modules.sql, modules.core], deduplicated=False)])
      ... # doctest: +NORMALIZE_WHITESPACE
      ['avro', 'catalyst', 'connect', 'core', 'docker-integration-tests', 'examples', 'graphx',
       'hive', 'hive-thriftserver', 'mllib', 'mllib-local', 'protobuf', 'pyspark-connect',
       'pyspark-core', 'pyspark-ml', 'pyspark-ml-connect', 'pyspark-mllib', 'pyspark-pandas',
       'pyspark-pandas-connect-part0', 'pyspark-pandas-connect-part1', 'pyspark-pandas-connect-part2',
       'pyspark-pandas-connect-part3', 'pyspark-pandas-slow', 'pyspark-resource', 'pyspark-sql',
       'pyspark-streaming', 'pyspark-testing', 'repl', 'root', 'sparkr', 'sql', 'sql-kafka-0-10',
       'streaming', 'streaming-kafka-0-10', 'streaming-kinesis-asl']
      """
      modules_to_test = set()
      for module in changed_modules:
          modules_to_test = modules_to_test.union(
              determine_modules_to_test(
                  module.dependent_modules, deduplicated
              )
          )
      modules_to_test = modules_to_test.union(set(changed_modules))
  
      if not deduplicated:
          return modules_to_test
  
      # If we need to run all of the tests, then we should short-circuit and return 'root'
      if modules.root in modules_to_test:
          return [modules.root]
      return toposort_flatten(
          {
              m: set(m.dependencies).intersection(modules_to_test)
              for m in modules_to_test
          },
          sort=True,
      )
  
file_path: spark/dev/sparktestsupport/utils.py
imports: import os
  import sys
  import subprocess
  from sparktestsupport import modules
  from sparktestsupport.shellutils import run_cmd
  from sparktestsupport.toposort import toposort_flatten
label_desc: Use image node_id 3 for calling a global function with example usage: determine_modules_to_test(changed_modules, deduplicated) and returns: toposort_flatten, modules_to_test, list