# Buggy code
def print_results(results):
    """
    Method to print the aggregated results from the profiler

    .. code-block:: python

        profiler.print_results(results)

    Example output:

    .. code-block:: text

        --------------------------------------------
        - Time profiling results:
        --------------------------------------------
        Processing function time stats (in seconds):
            min/index: (2.9754010029137135e-05, 0)
            max/index: (2.9754010029137135e-05, 0)
            mean: 2.9754010029137135e-05
            std: nan
            total: 2.9754010029137135e-05

        Dataflow time stats (in seconds):
            min/index: (0.2523871660232544, 0)
            max/index: (0.2523871660232544, 0)
            mean: 0.2523871660232544
            std: nan
            total: 0.2523871660232544

        Time stats of event handlers (in seconds):
        - Total time spent:
            1.0080009698867798

        - Events.STARTED:
            min/index: (0.1256754994392395, 0)
            max/index: (0.1256754994392395, 0)
            mean: 0.1256754994392395
            std: nan
            total: 0.1256754994392395

        Handlers names:
        ['BasicTimeProfiler._as_first_started', 'delay_start']
        --------------------------------------------
    """

    def odict_to_str(d):
        out = ""
        for k, v in d.items():
            out += "\t{}: {}\n".format(k, v)
        return out

    others = {
        k: odict_to_str(v) if isinstance(v, OrderedDict) else v
        for k, v in results["event_handlers_stats"].items()
    }

    others.update(results["event_handlers_names"])

    output_message = """
--------------------------------------------
- Time profiling results:
--------------------------------------------

Processing function time stats (in seconds):
{processing_stats}

Dataflow time stats (in seconds):
{dataflow_stats}

Time stats of event handlers (in seconds):
- Total time spent:
\t{total_time}

- Events.STARTED:
{Events_STARTED}
Handlers names:
{Events_STARTED_names}

- Events.EPOCH_STARTED:
{Events_EPOCH_STARTED}
Handlers names:
{Events_EPOCH_STARTED_names}

- Events.ITERATION_STARTED:
{Events_ITERATION_STARTED}
Handlers names:
{Events_ITERATION_STARTED_names}

- Events.ITERATION_COMPLETED:
{Events_ITERATION_COMPLETED}
Handlers names:
{Events_ITERATION_COMPLETED_names}

- Events.EPOCH_COMPLETED:
{Events_EPOCH_COMPLETED}
Handlers names:
{Events_EPOCH_COMPLETED_names}

- Events.COMPLETED:
{Events_COMPLETED}
Handlers names:
{Events_COMPLETED_names}

""".format(
        processing_stats=odict_to_str(results["processing_stats"]),
        dataflow_stats=odict_to_str(results["dataflow_stats"]),
        **others,
    )
    print(output_message)
    return output_message


# Traceback (KeyError)
OrderedDict([('processing_stats', OrderedDict([('min/index', (0.002581869950518012, 937)), ('max/index', (0.24407817423343658, 0)), ('mean', 0.005071939900517464), ('std', 0.005763144697993994), ('total', 9.514959335327148)])), ('dataflow_stats', OrderedDict([('min/index', (5.4130003263708204e-05, 1874)), ('max/index', (0.02181326039135456, 1875)), ('mean', 0.00013960782962385565), ('std', 0.0006590772536583245), ('total', 0.2619042992591858)])), ('event_handlers_stats', {'EPOCH_STARTED': OrderedDict([('min/index', (6.137001037131995e-06, 0)), ('max/index', (1.3475997548084706e-05, 1)), ('mean', 9.80649929260835e-06), ('std', 5.189453986531589e-06), ('total', 1.96129985852167e-05)]), 'EPOCH_COMPLETED': OrderedDict([('min/index', (3.951500654220581, 0)), ('max/index', (4.009259223937988, 1)), ('mean', 3.980380058288574), ('std', 0.0408414751291275), ('total', 7.960760116577148)]), 'STARTED': OrderedDict([('min/index', (4.647001333069056e-06, 0)), ('max/index', (4.647001333069056e-06, 0)), ('mean', 4.647001333069056e-06), ('std', nan), ('total', 4.647001333069056e-06)]), 'COMPLETED': OrderedDict([('min/index', (0.001252603018656373, 0)), ('max/index', (0.001252603018656373, 0)), ('mean', 0.001252603018656373), ('std', nan), ('total', 0.001252603018656373)]), 'ITERATION_STARTED': OrderedDict([('min/index', (1.2870004866272211e-06, 931)), ('max/index', (1.6206002328544855e-05, 784)), ('mean', 2.0810284695471637e-06), ('std', 1.0310620837117312e-06), ('total', 0.003904009470716119)]), 'ITERATION_COMPLETED': OrderedDict([('min/index', (0.00041244301246479154, 6)), ('max/index', (0.0033979369327425957, 1706)), ('mean', 0.0005990439676679671), ('std', 0.00017004708934109658), ('total', 1.1238064765930176)]), 'GET_BATCH_STARTED': OrderedDict([('min/index', (2.2699969122186303e-06, 1871)), ('max/index', (6.306700379354879e-05, 1627)), ('mean', 3.619041763158748e-06), ('std', 2.3099164536688477e-06), ('total', 0.006789322476834059)]), 'GET_BATCH_COMPLETED': OrderedDict([('min/index', (1.471998984925449e-06, 934)), ('max/index', (1.4063996786717325e-05, 918)), ('mean', 2.3078853246261133e-06), ('std', 8.762469292378228e-07), ('total', 0.0043295929208397865)]), 'total_time': tensor(9.1009)}), ('event_handlers_names', {'EPOCH_STARTED_names': ['Metric.started'], 'EPOCH_COMPLETED_names': ['ProgressBar._close', 'log_training_results_fn', 'log_validation_results_fn'], 'STARTED_names': ['BasicTimeProfiler._as_first_started'], 'COMPLETED_names': ['ModelCheckpoint'], 'ITERATION_STARTED_names': [], 'ITERATION_COMPLETED_names': ['Metric.iteration_completed', 'Metric.completed', 'LRScheduler', '_OutputHandler', 'Engine._handler_wrapper.<locals>.wrapper', 'Engine._handler_wrapper.<locals>.wrapper'], 'GET_BATCH_STARTED_names': [], 'GET_BATCH_COMPLETED_names': []})])
Traceback (most recent call last):
File "tutorials/mnist/mnist.py", line 228, in <module>
BasicTimeProfiler.print_results(profiler.get_results())
File "/work/desrozis/Softwares/conda/envs/focus-light/lib/python3.7/site-packages/ignite/contrib/handlers/time_profilers.py", line 414, in print_results
**others,
KeyError: 'Events_STARTED'

# Fixed code
def print_results(results):
    """
    Method to print the aggregated results from the profiler

    .. code-block:: python

        profiler.print_results(results)

    Example output:

    .. code-block:: text

        --------------------------------------------
        - Time profiling results:
        --------------------------------------------
        Processing function time stats (in seconds):
            min/index: (2.9754010029137135e-05, 0)
            max/index: (2.9754010029137135e-05, 0)
            mean: 2.9754010029137135e-05
            std: nan
            total: 2.9754010029137135e-05

        Dataflow time stats (in seconds):
            min/index: (0.2523871660232544, 0)
            max/index: (0.2523871660232544, 0)
            mean: 0.2523871660232544
            std: nan
            total: 0.2523871660232544

        Time stats of event handlers (in seconds):
        - Total time spent:
            1.0080009698867798

        - Events.STARTED:
            min/index: (0.1256754994392395, 0)
            max/index: (0.1256754994392395, 0)
            mean: 0.1256754994392395
            std: nan
            total: 0.1256754994392395

        Handlers names:
        ['BasicTimeProfiler._as_first_started', 'delay_start']
        --------------------------------------------
    """

    def odict_to_str(d):
        out = ""
        for k, v in d.items():
            out += "\t{}: {}\n".format(k, v)
        return out

    others = {
        k: odict_to_str(v) if isinstance(v, OrderedDict) else v
        for k, v in results["event_handlers_stats"].items()
    }

    others.update(results["event_handlers_names"])

    output_message = """
--------------------------------------------
- Time profiling results:
--------------------------------------------

Processing function time stats (in seconds):
{processing_stats}

Dataflow time stats (in seconds):
{dataflow_stats}

Time stats of event handlers (in seconds):
- Total time spent:
\t{total_time}

- Events.STARTED:
{STARTED}
Handlers names:
{STARTED_names}

- Events.EPOCH_STARTED:
{EPOCH_STARTED}
Handlers names:
{EPOCH_STARTED_names}

- Events.ITERATION_STARTED:
{ITERATION_STARTED}
Handlers names:
{ITERATION_STARTED_names}

- Events.ITERATION_COMPLETED:
{ITERATION_COMPLETED}
Handlers names:
{ITERATION_COMPLETED_names}

- Events.EPOCH_COMPLETED:
{EPOCH_COMPLETED}
Handlers names:
{EPOCH_COMPLETED_names}

- Events.COMPLETED:
{COMPLETED}
Handlers names:
{COMPLETED_names}

""".format(
        processing_stats=odict_to_str(results["processing_stats"]),
        dataflow_stats=odict_to_str(results["dataflow_stats"]),
        **others,
    )
    print(output_message)
    return output_message