mirror of
https://github.com/esphome/esphome.git
synced 2024-11-22 23:18:10 +01:00
Only try compat parsing after regular parsing fails (#2269)
This commit is contained in:
parent
0da97289e6
commit
1b5f11bbee
1 changed files with 78 additions and 68 deletions
|
@ -483,75 +483,9 @@ def parse_args(argv):
|
||||||
metavar=("key", "value"),
|
metavar=("key", "value"),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Keep backward compatibility with the old command line format of
|
|
||||||
# esphome <config> <command>.
|
|
||||||
#
|
|
||||||
# Unfortunately this can't be done by adding another configuration argument to the
|
|
||||||
# main config parser, as argparse is greedy when parsing arguments, so in regular
|
|
||||||
# usage it'll eat the command as the configuration argument and error out out
|
|
||||||
# because it can't parse the configuration as a command.
|
|
||||||
#
|
|
||||||
# Instead, construct an ad-hoc parser for the old format that doesn't actually
|
|
||||||
# process the arguments, but parses them enough to let us figure out if the old
|
|
||||||
# format is used. In that case, swap the command and configuration in the arguments
|
|
||||||
# and continue on with the normal parser (after raising a deprecation warning).
|
|
||||||
#
|
|
||||||
# Disable argparse's built-in help option and add it manually to prevent this
|
|
||||||
# parser from printing the help messagefor the old format when invoked with -h.
|
|
||||||
compat_parser = argparse.ArgumentParser(parents=[options_parser], add_help=False)
|
|
||||||
compat_parser.add_argument("-h", "--help")
|
|
||||||
compat_parser.add_argument("configuration", nargs="*")
|
|
||||||
compat_parser.add_argument(
|
|
||||||
"command",
|
|
||||||
choices=[
|
|
||||||
"config",
|
|
||||||
"compile",
|
|
||||||
"upload",
|
|
||||||
"logs",
|
|
||||||
"run",
|
|
||||||
"clean-mqtt",
|
|
||||||
"wizard",
|
|
||||||
"mqtt-fingerprint",
|
|
||||||
"version",
|
|
||||||
"clean",
|
|
||||||
"dashboard",
|
|
||||||
"vscode",
|
|
||||||
"update-all",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
# on Python 3.9+ we can simply set exit_on_error=False in the constructor
|
|
||||||
def _raise(x):
|
|
||||||
raise argparse.ArgumentError(None, x)
|
|
||||||
|
|
||||||
compat_parser.error = _raise
|
|
||||||
|
|
||||||
deprecated_argv_suggestion = None
|
|
||||||
|
|
||||||
if ["dashboard", "config"] == argv[1:3] or ["version"] == argv[1:2]:
|
|
||||||
# this is most likely meant in new-style arg format. do not try compat parsing
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
result, unparsed = compat_parser.parse_known_args(argv[1:])
|
|
||||||
last_option = len(argv) - len(unparsed) - 1 - len(result.configuration)
|
|
||||||
unparsed = [
|
|
||||||
"--device" if arg in ("--upload-port", "--serial-port") else arg
|
|
||||||
for arg in unparsed
|
|
||||||
]
|
|
||||||
argv = (
|
|
||||||
argv[0:last_option] + [result.command] + result.configuration + unparsed
|
|
||||||
)
|
|
||||||
deprecated_argv_suggestion = argv
|
|
||||||
except argparse.ArgumentError:
|
|
||||||
# This is not an old-style command line, so we don't have to do anything.
|
|
||||||
pass
|
|
||||||
|
|
||||||
# And continue on with regular parsing
|
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description=f"ESPHome v{const.__version__}", parents=[options_parser]
|
description=f"ESPHome v{const.__version__}", parents=[options_parser]
|
||||||
)
|
)
|
||||||
parser.set_defaults(deprecated_argv_suggestion=deprecated_argv_suggestion)
|
|
||||||
|
|
||||||
mqtt_options = argparse.ArgumentParser(add_help=False)
|
mqtt_options = argparse.ArgumentParser(add_help=False)
|
||||||
mqtt_options.add_argument("--topic", help="Manually set the MQTT topic.")
|
mqtt_options.add_argument("--topic", help="Manually set the MQTT topic.")
|
||||||
|
@ -701,7 +635,83 @@ def parse_args(argv):
|
||||||
"configuration", help="Your YAML configuration file directories.", nargs="+"
|
"configuration", help="Your YAML configuration file directories.", nargs="+"
|
||||||
)
|
)
|
||||||
|
|
||||||
return parser.parse_args(argv[1:])
|
# Keep backward compatibility with the old command line format of
|
||||||
|
# esphome <config> <command>.
|
||||||
|
#
|
||||||
|
# Unfortunately this can't be done by adding another configuration argument to the
|
||||||
|
# main config parser, as argparse is greedy when parsing arguments, so in regular
|
||||||
|
# usage it'll eat the command as the configuration argument and error out out
|
||||||
|
# because it can't parse the configuration as a command.
|
||||||
|
#
|
||||||
|
# Instead, if parsing using the current format fails, construct an ad-hoc parser
|
||||||
|
# that doesn't actually process the arguments, but parses them enough to let us
|
||||||
|
# figure out if the old format is used. In that case, swap the command and
|
||||||
|
# configuration in the arguments and retry with the normal parser (and raise
|
||||||
|
# a deprecation warning).
|
||||||
|
arguments = argv[1:]
|
||||||
|
|
||||||
|
# On Python 3.9+ we can simply set exit_on_error=False in the constructor
|
||||||
|
def _raise(x):
|
||||||
|
raise argparse.ArgumentError(None, x)
|
||||||
|
|
||||||
|
# First, try new-style parsing, but don't exit in case of failure
|
||||||
|
try:
|
||||||
|
# duplicate parser so that we can use the original one to raise errors later on
|
||||||
|
current_parser = argparse.ArgumentParser(add_help=False, parents=[parser])
|
||||||
|
current_parser.set_defaults(deprecated_argv_suggestion=None)
|
||||||
|
current_parser.error = _raise
|
||||||
|
return current_parser.parse_args(arguments)
|
||||||
|
except argparse.ArgumentError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Second, try compat parsing and rearrange the command-line if it succeeds
|
||||||
|
# Disable argparse's built-in help option and add it manually to prevent this
|
||||||
|
# parser from printing the help messagefor the old format when invoked with -h.
|
||||||
|
compat_parser = argparse.ArgumentParser(parents=[options_parser], add_help=False)
|
||||||
|
compat_parser.add_argument("-h", "--help", action="store_true")
|
||||||
|
compat_parser.add_argument("configuration", nargs="*")
|
||||||
|
compat_parser.add_argument(
|
||||||
|
"command",
|
||||||
|
choices=[
|
||||||
|
"config",
|
||||||
|
"compile",
|
||||||
|
"upload",
|
||||||
|
"logs",
|
||||||
|
"run",
|
||||||
|
"clean-mqtt",
|
||||||
|
"wizard",
|
||||||
|
"mqtt-fingerprint",
|
||||||
|
"version",
|
||||||
|
"clean",
|
||||||
|
"dashboard",
|
||||||
|
"vscode",
|
||||||
|
"update-all",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
compat_parser.error = _raise
|
||||||
|
result, unparsed = compat_parser.parse_known_args(argv[1:])
|
||||||
|
last_option = len(arguments) - len(unparsed) - 1 - len(result.configuration)
|
||||||
|
unparsed = [
|
||||||
|
"--device" if arg in ("--upload-port", "--serial-port") else arg
|
||||||
|
for arg in unparsed
|
||||||
|
]
|
||||||
|
arguments = (
|
||||||
|
arguments[0:last_option]
|
||||||
|
+ [result.command]
|
||||||
|
+ result.configuration
|
||||||
|
+ unparsed
|
||||||
|
)
|
||||||
|
deprecated_argv_suggestion = arguments
|
||||||
|
except argparse.ArgumentError:
|
||||||
|
# old-style parsing failed, don't suggest any argument
|
||||||
|
deprecated_argv_suggestion = None
|
||||||
|
|
||||||
|
# Finally, run the new-style parser again with the possibly swapped arguments,
|
||||||
|
# and let it error out if the command is unparsable.
|
||||||
|
parser.set_defaults(deprecated_argv_suggestion=deprecated_argv_suggestion)
|
||||||
|
return parser.parse_args(arguments)
|
||||||
|
|
||||||
|
|
||||||
def run_esphome(argv):
|
def run_esphome(argv):
|
||||||
|
@ -715,7 +725,7 @@ def run_esphome(argv):
|
||||||
"and will be removed in the future. "
|
"and will be removed in the future. "
|
||||||
)
|
)
|
||||||
_LOGGER.warning("Please instead use:")
|
_LOGGER.warning("Please instead use:")
|
||||||
_LOGGER.warning(" esphome %s", " ".join(args.deprecated_argv_suggestion[1:]))
|
_LOGGER.warning(" esphome %s", " ".join(args.deprecated_argv_suggestion))
|
||||||
|
|
||||||
if sys.version_info < (3, 7, 0):
|
if sys.version_info < (3, 7, 0):
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
|
|
Loading…
Reference in a new issue