-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Corresponding logic will be moved to robotpy-meta - __main__ will no longer be the user's robot code, but I don't think anything uses that? - Fixes #51
- Loading branch information
Showing
7 changed files
with
120 additions
and
301 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,227 +1,18 @@ | ||
# novalidate | ||
|
||
import argparse | ||
import inspect | ||
import os | ||
import sys | ||
|
||
from os.path import exists | ||
import importlib.metadata | ||
|
||
from .logconfig import configure_logging | ||
|
||
if sys.version_info < (3, 10): | ||
|
||
def entry_points(group): | ||
eps = importlib.metadata.entry_points() | ||
return eps.get(group) | ||
|
||
else: | ||
entry_points = importlib.metadata.entry_points | ||
|
||
|
||
def _log_versions(): | ||
import wpilib | ||
import wpilib.deployinfo | ||
|
||
import logging | ||
|
||
data = wpilib.deployinfo.getDeployData() | ||
if data: | ||
logger = logging.getLogger("deploy-info") | ||
logger.info( | ||
"%s@%s at %s", | ||
data.get("deploy-user", "<unknown>"), | ||
data.get("deploy-host", "<unknown>"), | ||
data.get("deploy-date", "<unknown>"), | ||
) | ||
if "git-hash" in data: | ||
logger.info( | ||
"- git info: %s (branch=%s)", | ||
data.get("git-desc", "<unknown>"), | ||
data.get("git-branch", "<unknown>"), | ||
) | ||
|
||
logger = logging.getLogger("wpilib") | ||
|
||
try: | ||
import robotpy.version | ||
except ImportError: | ||
robotpy_version = None | ||
else: | ||
logger.info("RobotPy version %s", robotpy.version.__version__) | ||
|
||
logger.info("WPILib version %s", wpilib.__version__) | ||
|
||
if wpilib.RobotBase.isSimulation(): | ||
logger.info("Running with simulated HAL.") | ||
|
||
# check to see if we're on a RoboRIO | ||
# NOTE: may have false positives, but it should work well enough | ||
if exists("/etc/natinst/share/scs_imagemetadata.ini"): | ||
logger.warning( | ||
"Running simulation HAL on actual roboRIO! This probably isn't what you want, and will probably cause difficult-to-debug issues!" | ||
) | ||
|
||
if logger.isEnabledFor(logging.DEBUG): | ||
versions = {} | ||
|
||
# Log third party versions | ||
for group in ("robotpylib", "robotpybuild"): | ||
for entry_point in entry_points(group=group): | ||
# Don't actually load the entry points -- just print the | ||
# packages unless we need to load them | ||
dist = entry_point.dist | ||
versions[dist.name] = dist.version | ||
|
||
for k, v in versions.items(): | ||
if k != "wpilib": | ||
logger.debug("%s version %s", k, v) | ||
|
||
|
||
def _enable_faulthandler(): | ||
# | ||
# In the event of a segfault, faulthandler will dump the currently | ||
# active stack so you can figure out what went wrong. | ||
# | ||
# Additionally, on non-Windows platforms we register a SIGUSR2 | ||
# handler -- if you send the robot process a SIGUSR2, then | ||
# faulthandler will dump all of your current stacks. This can | ||
# be really useful for figuring out things like deadlocks. | ||
# | ||
|
||
import logging | ||
|
||
logger = logging.getLogger("faulthandler") | ||
|
||
try: | ||
# These should work on all platforms | ||
import faulthandler | ||
|
||
faulthandler.enable() | ||
except Exception as e: | ||
logger.warn("Could not enable faulthandler: %s", e) | ||
return | ||
|
||
try: | ||
import signal | ||
|
||
faulthandler.register(signal.SIGUSR2) | ||
logger.info("registered SIGUSR2 for PID %s", os.getpid()) | ||
except Exception: | ||
return | ||
|
||
|
||
class _CustomHelpAction(argparse.Action): | ||
def __init__( | ||
self, | ||
option_strings, | ||
dest=argparse.SUPPRESS, | ||
default=argparse.SUPPRESS, | ||
help=None, | ||
): | ||
super(_CustomHelpAction, self).__init__( | ||
option_strings=option_strings, | ||
dest=dest, | ||
default=default, | ||
nargs=0, | ||
help=help, | ||
) | ||
|
||
def __call__(self, parser, namespace, values, option_string=None): | ||
parser.print_help() | ||
parser.exit(1) # argparse uses an exit code of zero by default | ||
|
||
|
||
argparse._HelpAction = _CustomHelpAction | ||
|
||
|
||
def run(robot_class, **kwargs): | ||
""" | ||
This function gets called in robot.py like so:: | ||
if __name__ == '__main__': | ||
wpilib.run(MyRobot) | ||
``wpilib.run`` is no longer used. You should run your robot code via one of | ||
the following methods instead: | ||
This function loads available entry points, parses arguments, and | ||
sets things up specific to RobotPy so that the robot can run. This | ||
function is used whether the code is running on the roboRIO or | ||
a simulation. | ||
* Windows: ``py -m robotpy [arguments]`` | ||
* Linux/macOS: ``python -m robotpy [arguments]`` | ||
:param robot_class: A class that inherits from :class:`.RobotBase` | ||
:param kwargs: Keyword arguments that will be passed to the executed entry points | ||
:returns: This function should never return | ||
In a virtualenv the ``robotpy`` command can be used directly. | ||
""" | ||
|
||
# sanity check | ||
if not hasattr(robot_class, "main"): | ||
print( | ||
"ERROR: run() must be passed a robot class that inherits from RobotBase (or IterativeBase/SampleBase)" | ||
) | ||
exit(1) | ||
|
||
parser = argparse.ArgumentParser() | ||
subparser = parser.add_subparsers(dest="command", help="commands") | ||
subparser.required = True | ||
|
||
parser.add_argument( | ||
"-v", | ||
"--verbose", | ||
action="store_true", | ||
default=False, | ||
help="Enable debug logging", | ||
) | ||
|
||
parser.add_argument( | ||
"--ignore-plugin-errors", | ||
action="store_true", | ||
default=False, | ||
help="Ignore errors caused by RobotPy plugins (probably should fix or replace instead!)", | ||
) | ||
|
||
has_cmd = False | ||
|
||
for entry_point in entry_points(group="robotpy"): | ||
try: | ||
cmd_class = entry_point.load() | ||
except ImportError: | ||
if "--ignore-plugin-errors" in sys.argv: | ||
print("WARNING: Ignoring error in '%s'" % entry_point) | ||
continue | ||
else: | ||
print( | ||
"Plugin error detected in '%s' (use --ignore-plugin-errors to ignore this)" | ||
% entry_point | ||
) | ||
raise | ||
|
||
cmdparser = subparser.add_parser( | ||
entry_point.name, help=inspect.getdoc(cmd_class) | ||
) | ||
obj = cmd_class(cmdparser) | ||
cmdparser.set_defaults(cmdobj=obj) | ||
has_cmd = True | ||
|
||
if not has_cmd: | ||
parser.error( | ||
"No entry points defined -- robot code can't do anything. Install packages to add entry points (see README)" | ||
) | ||
exit(1) | ||
|
||
options = parser.parse_args() | ||
|
||
configure_logging(options.verbose) | ||
|
||
_log_versions() | ||
_enable_faulthandler() | ||
|
||
retval = options.cmdobj.run(options, robot_class, **kwargs) | ||
|
||
if retval is None: | ||
retval = 0 | ||
elif retval is True: | ||
retval = 0 | ||
elif retval is False: | ||
retval = 1 | ||
|
||
exit(retval) | ||
msg = inspect.cleandoc(inspect.getdoc(run) or "`wpilib.run` is no longer used") | ||
print(msg, file=sys.stderr) | ||
sys.exit(1) |
Oops, something went wrong.