Verified Commit cdfb0750 authored by Raphaël Bleuse's avatar Raphaël Bleuse
Browse files

Implement detection of ambiguous schedulers

The names of entry points is not guaranteed to be unique across all
packages: schedulers defined in different packages may use the same
entry point name.
If a user requests to run a scheduler (identified by the name of its
entry point) that is bound to multiple classes, the execution is aborted
as there is no way to univocally choose a scheduler.
Note that the execution continues as long as the user requests to run a
scheduler bound to a single class, even if some other ambiguous
schedulers exist.
parent b01927d5
......@@ -8,9 +8,11 @@
import argparse
import io
import json
import sys
from pybatsim import __version__
from pybatsim.plugin import SCHEDULER_ENTRY_POINT, find_plugin_schedulers
from pybatsim.plugin import (SCHEDULER_ENTRY_POINT, find_ambiguous_scheduler_names,
find_plugin_schedulers)
from pybatsim.batsim.tools.launcher import launch_scheduler as legacy_launch_scheduler
......@@ -101,10 +103,24 @@ def _build_parser():
return parser
def _abort_on_ambiguous_scheduler_name(name):
ambiguous_names = find_ambiguous_scheduler_names()
if name in ambiguous_names:
print(
f'Error in definition of \'{SCHEDULER_ENTRY_POINT}\' entry point,',
'check your packaging!',
f'\'{name}\' is defined more than once, and binds to:',
', '.join(ambiguous_names[name]),
file=sys.stderr,
)
sys.exit(1)
def main(args=None):
parser = _build_parser()
arguments = parser.parse_args(args)
# instantiate scheduler
_abort_on_ambiguous_scheduler_name(arguments.scheduler)
scheduler = get_scheduler_by_name(arguments.scheduler, options=arguments.scheduler_options)
# launch simulation
legacy_launch_scheduler(
......
......@@ -5,6 +5,7 @@
PyBatsim plugin interface.
"""
import collections
import sys
# selectable entry points were introduced in Python 3.10
......@@ -20,3 +21,21 @@ SCHEDULER_ENTRY_POINT = 'pybatsim.schedulers'
def find_plugin_schedulers():
for scheduler in entry_points(group=SCHEDULER_ENTRY_POINT):
yield scheduler.name, scheduler.load()
def find_ambiguous_scheduler_names():
"""
Return the dict of names bound to multiple schedulers.
For each ambiguous name, the dict maps the name to the set of entry points
values.
"""
known_scheduler_names = collections.defaultdict(set)
for scheduler in entry_points(group=SCHEDULER_ENTRY_POINT):
known_scheduler_names[scheduler.name].add(scheduler.value)
ambiguous_scheduler_names = {
name: values
for (name, values) in known_scheduler_names.items()
if len(values) > 1
}
return ambiguous_scheduler_names
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment