diff --git a/apio/__main__.py b/apio/__main__.py index 8ae7b9ad..20f84579 100644 --- a/apio/__main__.py +++ b/apio/__main__.py @@ -103,6 +103,16 @@ def select_commands_help(command_lines, command_names): return result +def context_settings(): + """Return a common Click command settings that adds + the alias -h to --help. This applies also to all the sub + commands such as apio build. + """ + # Per https://click.palletsprojects.com/en/8.1.x/documentation/ + # #help-parameter-customization + return {"help_option_names": ["-h", "--help"]} + + # --------------------------- # -- Top click command node. # --------------------------- @@ -118,7 +128,7 @@ def select_commands_help(command_lines, command_names): Apio commands are typically invoked in the root directory of the FPGA project where the project configuration file apio.ini and the project source files are stored. For help on specific commands use the -h -flag (e.g. apio build -h). +flag (e.g. 'apio build -h'). For more information on the apio project see https://github.com/FPGAwars/apio/wiki/Apio @@ -129,7 +139,7 @@ def select_commands_help(command_lines, command_names): cls=ApioCLI, help=HELP, invoke_without_command=True, - context_settings=util.context_settings(), + context_settings=context_settings(), ) @click.pass_context @click.version_option() diff --git a/apio/commands/boards.py b/apio/commands/boards.py index 643a8180..f489a652 100644 --- a/apio/commands/boards.py +++ b/apio/commands/boards.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO BOARDS command""" +"""Implementation of 'apio boards' command""" from pathlib import Path import click @@ -23,6 +23,7 @@ "--fpga", is_flag=True, help="List supported FPGA chips.", + cls=util.ApioOption, ) @@ -50,7 +51,7 @@ "boards", short_help="List supported boards and FPGAs.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @options.project_dir_option diff --git a/apio/commands/build.py b/apio/commands/build.py index 916d7045..19337d31 100644 --- a/apio/commands/build.py +++ b/apio/commands/build.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO BUILD command""" +"""Implementation of 'apio build' command""" from pathlib import Path import click @@ -29,10 +29,6 @@ Examples: apio build apio build -v - -[Note] The flags marked with (deprecated) are not recomanded. -Instead, use an apio.ini project config file and if neaded, add -to the project custom boards.json and fpga.json files. """ @@ -42,15 +38,15 @@ "build", short_help="Synthesize the bitstream.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @options.project_dir_option @options.verbose_option @options.verbose_yosys_option @options.verbose_pnr_option -@options.top_module_option_gen() -@options.board_option_gen() +@options.top_module_option_gen(deprecated=True) +@options.board_option_gen(deprecated=True) @options.fpga_option @options.size_option @options.type_option diff --git a/apio/commands/clean.py b/apio/commands/clean.py index e3ca1a1e..93fa07ba 100644 --- a/apio/commands/clean.py +++ b/apio/commands/clean.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO CLEAN command""" +"""Implementation of 'apio clean' command""" from pathlib import Path import click @@ -28,10 +28,6 @@ Example: apio clean -[Note] The flags marked with (deprecated) are not recomanded. -Instead, use an apio.ini project config file and if neaded, add -to the project custom boards.json and fpga.json files. - [Hint] If you are using a git repository, add a .gitignore file with the temporary apio file names. """ @@ -41,12 +37,12 @@ "clean", short_help="Clean the apio generated files.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @options.project_dir_option @options.verbose_option -@options.board_option_gen() +@options.board_option_gen(deprecated=True) def cli( ctx: Context, # Options diff --git a/apio/commands/create.py b/apio/commands/create.py index 7d0d8263..d1629d57 100644 --- a/apio/commands/create.py +++ b/apio/commands/create.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO CREATE command""" +"""Implementation of 'apio create' command""" from pathlib import Path import click @@ -50,7 +50,7 @@ "create", short_help="Create an apio.ini project file.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @options.board_option_gen(help="Set the board.", required=True) diff --git a/apio/commands/drivers.py b/apio/commands/drivers.py index 735957a8..4dbea116 100644 --- a/apio/commands/drivers.py +++ b/apio/commands/drivers.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO DRIVERS command""" +"""Implementation of 'apio drivers' command""" import click from click.core import Context @@ -20,6 +20,7 @@ "--ftdi-enable", is_flag=True, help="Enable FTDI drivers.", + cls=util.ApioOption, ) ftdi_disable_option = click.option( @@ -27,6 +28,7 @@ "--ftdi-disable", is_flag=True, help="Disable FTDI drivers.", + cls=util.ApioOption, ) serial_enable_option = click.option( @@ -34,6 +36,7 @@ "--serial-enable", is_flag=True, help="Enable Serial drivers.", + cls=util.ApioOption, ) serial_disable_option = click.option( @@ -41,6 +44,7 @@ "--serial-disable", is_flag=True, help="Disable Serial drivers.", + cls=util.ApioOption, ) @@ -68,7 +72,7 @@ "drivers", short_help="Manage the operating system drivers.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @frdi_enable_option diff --git a/apio/commands/examples.py b/apio/commands/examples.py index 372aaa13..a0b0cf82 100644 --- a/apio/commands/examples.py +++ b/apio/commands/examples.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO EXAMPLES command""" +"""Implementation of 'apio examples' command""" from pathlib import Path import click @@ -24,6 +24,7 @@ type=str, metavar="name", help="Copy the selected example directory.", + cls=util.ApioOption, ) files_option = click.option( @@ -33,6 +34,7 @@ type=str, metavar="name", help="Copy the selected example files.", + cls=util.ApioOption, ) @@ -58,7 +60,7 @@ "examples", short_help="List and fetch apio examples.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @options.list_option_gen(help="List all available examples.") diff --git a/apio/commands/graph.py b/apio/commands/graph.py index 28a6e4cb..878f7d85 100644 --- a/apio/commands/graph.py +++ b/apio/commands/graph.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO GRAPH command""" +"""Implementation of 'apio graph' command""" from pathlib import Path import click @@ -42,7 +42,7 @@ "graph", short_help="Generate a visual graph of the code.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @options.project_dir_option diff --git a/apio/commands/init.py b/apio/commands/init.py index dfb6dc62..9cffd169 100644 --- a/apio/commands/init.py +++ b/apio/commands/init.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO INIT command""" +"""Implementation of 'apio init' command""" # pylint: disable=fixme # TODO: After migrating IceStudio to the create/modify commands, delete @@ -28,6 +28,7 @@ "--scons", is_flag=True, help="(Advanced, for developers) Create default SConstruct file.", + cls=util.ApioOption, ) @@ -44,9 +45,9 @@ # pylint: disable=R0913 @click.command( "init", - short_help="(deprecated) Manage apio projects.", + short_help="[DEPRECATED] Manage apio projects.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @options.board_option_gen(help="Create init file with the selected board.") diff --git a/apio/commands/install.py b/apio/commands/install.py index ad3b96d6..18d85f0b 100644 --- a/apio/commands/install.py +++ b/apio/commands/install.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO INSTALL command""" +"""Implementation of 'apio install' command""" from pathlib import Path from typing import Tuple @@ -60,7 +60,7 @@ def install_packages( "install", short_help="Install apio packages.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @click.argument("packages", nargs=-1, required=False) diff --git a/apio/commands/lint.py b/apio/commands/lint.py index 2f48d568..a3f522b9 100644 --- a/apio/commands/lint.py +++ b/apio/commands/lint.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO LINT command""" +"""Implementation of 'apio lint' command""" from pathlib import Path import click @@ -23,6 +23,7 @@ "--nostyle", is_flag=True, help="Disable all style warnings.", + cls=util.ApioOption, ) @@ -32,6 +33,7 @@ type=str, metavar="nowarn", help="Disable specific warning(s).", + cls=util.ApioOption, ) warn_option = click.option( @@ -40,6 +42,7 @@ type=str, metavar="warn", help="Enable specific warning(s).", + cls=util.ApioOption, ) @@ -57,8 +60,6 @@ \b Examples: apio lint - -[Note] The flags marked with (deprecated) are not recomanded for use. """ @@ -68,7 +69,7 @@ "lint", short_help="Lint the verilog code.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @options.all_option_gen( @@ -78,7 +79,7 @@ @nowarn_option @warn_option @options.project_dir_option -@options.top_module_option_gen() +@options.top_module_option_gen(deprecated=True) def cli( ctx: Context, # Options diff --git a/apio/commands/modify.py b/apio/commands/modify.py index 64d4a4dd..2d5d5a8b 100644 --- a/apio/commands/modify.py +++ b/apio/commands/modify.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO MODIFY command""" +"""Implementation of 'apio modify' command""" from pathlib import Path import click @@ -42,7 +42,7 @@ "modify", short_help="Modify the apio.ini project file.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @options.board_option_gen(help="Set the board.") diff --git a/apio/commands/options.py b/apio/commands/options.py index 81bdff12..eebd6baa 100644 --- a/apio/commands/options.py +++ b/apio/commands/options.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Common APIO command options""" +"""Common apio command options""" from pathlib import Path import click @@ -35,6 +35,7 @@ def all_option_gen(*, help: str): "--all", is_flag=True, help=help, + cls=util.ApioOption, ) @@ -48,6 +49,7 @@ def force_option_gen(*, help: str): "--force", is_flag=True, help=help, + cls=util.ApioOption, ) @@ -61,13 +63,14 @@ def list_option_gen(*, help: str): "--list", is_flag=True, help=help, + cls=util.ApioOption, ) # W0622: Redefining built-in 'help' # pylint: disable=W0622 def board_option_gen( - *, help: str = "(deprecated) Set the board.", required=False + *, deprecated: bool = False, required=False, help: str = "Set the board." ): """Generate a --board option with given help text.""" return click.option( @@ -77,7 +80,9 @@ def board_option_gen( type=str, required=required, metavar="str", + deprecated=deprecated, help=help, + cls=util.ApioOption, ) @@ -85,7 +90,8 @@ def board_option_gen( # pylint: disable=W0622 def top_module_option_gen( *, - help: str = "(deprecated) Set the top level module name.", + deprecated: bool = False, + help: str = "Set the top level module name.", ): """Generate a --top-module option with given help text.""" return click.option( @@ -94,7 +100,9 @@ def top_module_option_gen( "--top-module", type=str, metavar="name", + deprecated=deprecated, help=help, + cls=util.ApioOption, ) @@ -108,7 +116,9 @@ def top_module_option_gen( "--fpga", type=str, metavar="str", - help="(deprecated) Set the FPGA.", + deprecated=True, + help="Set the FPGA.", + cls=util.ApioOption, ) ftdi_id = click.option( @@ -124,7 +134,9 @@ def top_module_option_gen( "--pack", type=str, metavar="str", - help="(deprecated) Set the FPGA package.", + deprecated=True, + help="Set the FPGA package.", + cls=util.ApioOption, ) @@ -134,6 +146,7 @@ def top_module_option_gen( "--platform", type=click.Choice(util.PLATFORMS), help=("(Advanced, for developers) Set the platform."), + cls=util.ApioOption, ) @@ -144,6 +157,7 @@ def top_module_option_gen( type=Path, metavar="path", help="Set the root directory for the project.", + cls=util.ApioOption, ) @@ -153,6 +167,7 @@ def top_module_option_gen( "--sayno", is_flag=True, help="Automatically answer NO to all the questions.", + cls=util.ApioOption, ) sayyes = click.option( @@ -161,6 +176,7 @@ def top_module_option_gen( "--sayyes", is_flag=True, help="Automatically answer YES to all the questions.", + cls=util.ApioOption, ) serial_port_option = click.option( @@ -169,6 +185,7 @@ def top_module_option_gen( type=str, metavar="serial-port", help="Set the serial port.", + cls=util.ApioOption, ) @@ -177,7 +194,9 @@ def top_module_option_gen( "--size", type=str, metavar="str", - help="(deprecated) Set the FPGA type (1k/8k).", + deprecated=True, + help="Set the FPGA type (1k/8k).", + cls=util.ApioOption, ) @@ -186,7 +205,9 @@ def top_module_option_gen( "--type", type=str, metavar="str", - help="(deprecated) Set the FPGA type (hx/lp).", + deprecated=True, + help="Set the FPGA type (hx/lp).", + cls=util.ApioOption, ) @@ -196,6 +217,7 @@ def top_module_option_gen( "--verbose", is_flag=True, help="Show the entire output of the command.", + cls=util.ApioOption, ) @@ -204,6 +226,7 @@ def top_module_option_gen( "--verbose-pnr", is_flag=True, help="Show the pnr output.", + cls=util.ApioOption, ) @@ -212,4 +235,5 @@ def top_module_option_gen( "--verbose-yosys", is_flag=True, help="Show the yosys output.", + cls=util.ApioOption, ) diff --git a/apio/commands/raw.py b/apio/commands/raw.py index 712e8b2a..726294b6 100644 --- a/apio/commands/raw.py +++ b/apio/commands/raw.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO RAW command""" +"""Implementation of 'apio raw' command""" import click from click.core import Context @@ -36,7 +36,7 @@ "raw", short_help="Execute commands directly from the Apio packages.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @click.argument("cmd") diff --git a/apio/commands/sim.py b/apio/commands/sim.py index 02bb1d7e..0862cbd2 100644 --- a/apio/commands/sim.py +++ b/apio/commands/sim.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO SIM command""" +"""Implementation of 'apio sim' command""" from pathlib import Path import click @@ -42,7 +42,7 @@ "sim", short_help="Simulate a testbench with graphic results.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @click.argument("testbench", nargs=1, required=True) diff --git a/apio/commands/system.py b/apio/commands/system.py index 246d2871..45095e77 100644 --- a/apio/commands/system.py +++ b/apio/commands/system.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO SYSTEM command""" +"""Implementation of 'apio system' command""" from pathlib import Path import inspect @@ -25,6 +25,7 @@ "--lsftdi", is_flag=True, help="List all connected FTDI devices.", + cls=util.ApioOption, ) lsusb_option = click.option( @@ -32,6 +33,7 @@ "--lsusb", is_flag=True, help="List all connected USB devices.", + cls=util.ApioOption, ) lsserial_option = click.option( @@ -39,6 +41,7 @@ "--lsserial", is_flag=True, help="List all connected Serial devices.", + cls=util.ApioOption, ) info_option = click.option( @@ -47,6 +50,7 @@ "--info", is_flag=True, help="Show platform id and other info.", + cls=util.ApioOption, ) @@ -75,7 +79,7 @@ "system", short_help="Provides system info.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @options.project_dir_option diff --git a/apio/commands/test.py b/apio/commands/test.py index 10b564f0..2717b43b 100644 --- a/apio/commands/test.py +++ b/apio/commands/test.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO TEST command""" +"""Implementation of 'apio test' command""" from pathlib import Path import click @@ -27,8 +27,8 @@ \b Examples - apio test my_module_tb.v # Run a single testbench apio test # Run all *_tb.v testbenches. + apio test my_module_tb.v # Run a single testbench For a sample testbench that is compatible with apio see the example at @@ -43,7 +43,7 @@ "test", short_help="Test all or a single verilog testbench module.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @click.argument("testbench_file", nargs=1, required=False) diff --git a/apio/commands/time.py b/apio/commands/time.py index b8d6bb25..4338534e 100644 --- a/apio/commands/time.py +++ b/apio/commands/time.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO time command""" +"""Implementation of 'apio' time' command""" from pathlib import Path import click @@ -30,10 +30,6 @@ \b Examples: apio time - -[Note] The flags marked with (deprecated) are not recomanded. -Instead, use an apio.ini project config file and if neaded, add -to the project custom boards.json and fpga.json files. """ @@ -45,15 +41,15 @@ "time", short_help="Report design timing.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @options.project_dir_option @options.verbose_option @options.verbose_yosys_option @options.verbose_pnr_option -@options.top_module_option_gen() -@options.board_option_gen() +@options.top_module_option_gen(deprecated=True) +@options.board_option_gen(deprecated=True) @options.fpga_option @options.size_option @options.type_option diff --git a/apio/commands/uninstall.py b/apio/commands/uninstall.py index 0b04ad72..e58d4f01 100644 --- a/apio/commands/uninstall.py +++ b/apio/commands/uninstall.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO UNINSTALL command""" +"""Implementation of 'apio uninstall' command""" from pathlib import Path from typing import Tuple @@ -61,7 +61,7 @@ def _uninstall(packages: list, platform: str, resources: Resources): "uninstall", short_help="Uninstall apio packages.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @click.argument("packages", nargs=-1, required=False) diff --git a/apio/commands/upgrade.py b/apio/commands/upgrade.py index 64e7f1d9..87b37656 100644 --- a/apio/commands/upgrade.py +++ b/apio/commands/upgrade.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO UPGRADE command""" +"""Implementation of 'apio upgrade' command""" import importlib.metadata import click @@ -32,7 +32,7 @@ "upgrade", short_help="Check the latest Apio version.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context def cli(ctx: Context): diff --git a/apio/commands/upload.py b/apio/commands/upload.py index 5c4e5fdb..63fe4315 100644 --- a/apio/commands/upload.py +++ b/apio/commands/upload.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Implement the apio upload command""" +"""Implementation of 'apio upload' command""" from pathlib import Path import click @@ -25,6 +25,7 @@ "--sram", is_flag=True, help="Perform SRAM programming.", + cls=util.ApioOption, ) flash_option = click.option( @@ -33,6 +34,7 @@ "--flash", is_flag=True, help="Perform FLASH programming.", + cls=util.ApioOption, ) @@ -49,10 +51,6 @@ \b Examples: apio upload - -[Note] The flags marked with (deprecated) are not recomanded. -Instead, use an apio.ini project config file and if neaded, add -to the project custom boards.json and fpga.json files. """ @@ -64,7 +62,7 @@ "upload", short_help="Upload the bitstream to the FPGA.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @options.project_dir_option @@ -75,8 +73,8 @@ @options.verbose_option @options.verbose_yosys_option @options.verbose_pnr_option -@options.top_module_option_gen() -@options.board_option_gen() +@options.top_module_option_gen(deprecated=True) +@options.board_option_gen(deprecated=True) def cli( ctx: Context, # Options diff --git a/apio/commands/verify.py b/apio/commands/verify.py index ea1d1064..dfe9eb22 100644 --- a/apio/commands/verify.py +++ b/apio/commands/verify.py @@ -5,7 +5,7 @@ # -- * Jesús Arroyo (2016-2019) # -- * Juan Gonzalez (obijuan) (2019-2024) # -- Licence GPLv2 -"""Main implementation of APIO VERIFY command""" +"""Implementation of 'apio verify' command""" from pathlib import Path import click @@ -38,12 +38,12 @@ "verify", short_help="Verify project's verilog code.", help=HELP, - context_settings=util.context_settings(), + cls=util.ApioCommand, ) @click.pass_context @options.project_dir_option @options.verbose_option -@options.board_option_gen() +@options.board_option_gen(deprecated=True) def cli( ctx: Context, # Options diff --git a/apio/managers/arguments.py b/apio/managers/arguments.py index 10323440..f47c2ae9 100644 --- a/apio/managers/arguments.py +++ b/apio/managers/arguments.py @@ -154,7 +154,10 @@ def process_arguments( # -- given in args is different than the one in the project, # -- inform the user if config[BOARD] != project.board: - click.secho("Info: ignore apio.ini board", fg="yellow") + click.secho( + "Info: ignoring board specification from apio.ini.", + fg="yellow", + ) # -- Board name given in the project file else: diff --git a/apio/resources.py b/apio/resources.py index fcc1fe96..9b4c4088 100644 --- a/apio/resources.py +++ b/apio/resources.py @@ -129,7 +129,8 @@ def _load_resource(self, name: str, allow_custom: bool = False) -> dict: if filepath.exists(): if allow_custom: click.secho( - f"Loading custom {name} from project dir", fg="yellow" + f"Info: Loading custom {name} from the project dir.", + fg="yellow", ) return self._load_resource_file(filepath) diff --git a/apio/util.py b/apio/util.py index 62cdb537..4b2af4cb 100644 --- a/apio/util.py +++ b/apio/util.py @@ -16,6 +16,7 @@ import subprocess from threading import Thread from pathlib import Path +from typing import Mapping, List, Tuple, Any import click import semantic_version from serial.tools.list_ports import comports @@ -40,6 +41,8 @@ OSS_CAD_SUITE_FOLDER = f"tools-{OSS_CAD_SUITE}" GTKWAVE_FOLDER = f"tool-{GTKWAVE}" +DEPRECATED_MARKER = "[DEPRECATED]" + # -- AVAILABLE PLATFORMS PLATFORMS = [ "linux", @@ -880,15 +883,6 @@ def get_python_version() -> str: return f"{sys.version_info[0]}.{sys.version_info[1]}" -def context_settings(): - """Return a common Click command settings that adds - the alias -h to --help - """ - # Per https://click.palletsprojects.com/en/8.1.x/documentation/ - # #help-parameter-customization - return {"help_option_names": ["-h", "--help"]} - - def safe_click(text, *args, **kwargs): """Prints text to the console handling potential Unicode errors, forwarding any additional arguments to click.echo. This permits @@ -905,3 +899,61 @@ def safe_click(text, *args, **kwargs): # most common character error cleaned_text = "".join([ch if ord(ch) < 128 else "=" for ch in text]) click.echo(cleaned_text, err=error_flag, *args, **kwargs) + + +class ApioOption(click.Option): + """Custom class for apio click options. Currently it adds handling + of deprecated options. + """ + + def __init__(self, *args, **kwargs): + # Cache a list of option's aliases. E.g. ["-t", "--top-model"]. + self.aliases = [k for k in args[0] if k.startswith("-")] + # Consume the "deprecated" arg is specified. This args is + # added by this class and is not passed to super. + self.deprecated = kwargs.pop("deprecated", False) + # Tweak the help text to have a [DEPRECATED] prefix. + if self.deprecated: + kwargs["help"] = ( + DEPRECATED_MARKER + " " + kwargs.get("help", "").strip() + ) + super().__init__(*args, **kwargs) + + # @override + def handle_parse_result( + self, ctx: click.Context, opts: Mapping[str, Any], args: List[str] + ) -> Tuple[Any, List[str]]: + """Overides the parent method to print a deprecated option message.""" + if self.deprecated and self.name in opts: + click.secho(f"Info: {self.aliases} is deprecated.", fg="yellow") + return super().handle_parse_result(ctx, opts, args) + + +DEPRECATION_NOTE = f""" +[Note] Flags marked with {DEPRECATED_MARKER} are not recomanded for use. +For project configuration, use an apio.ini project file and if neaded, +project specific 'boards.json' and 'fpga.json' definition files. +""" + + +class ApioCommand(click.Command): + """Override click.Command with Apio specific behavior.""" + + def _num_deprecated_options(self, ctx: click.Context) -> None: + """Return sthe number of deprecated options of this command.""" + deprecated_options = 0 + for param in self.get_params(ctx): + if isinstance(param, ApioOption) and param.deprecated: + deprecated_options += 1 + return deprecated_options + + # @override + def format_help_text( + self, ctx: click.Context, formatter: click.HelpFormatter + ) -> None: + super().format_help_text(ctx, formatter) + deprecated = self._num_deprecated_options(ctx) + if deprecated > 0: + formatter.write_paragraph() + with formatter.indentation(): + formatter.write_text(DEPRECATION_NOTE) diff --git a/test/code_commands/test_build.py b/test/code_commands/test_build.py index c70f30bf..1169ccf7 100644 --- a/test/code_commands/test_build.py +++ b/test/code_commands/test_build.py @@ -259,7 +259,7 @@ def test_build_init(clirunner, configenv): # apio build --board icezum result = clirunner.invoke(cmd_build, ["--board", "icestick"]) assert result.exit_code != 0 - assert "Info: ignore apio.ini board" in result.output + assert "Info: ignoring board specification from apio.ini." in result.output # apio build --fpga iCE40-HX1K-VQ100 result = clirunner.invoke(cmd_build, ["--fpga", "iCE40-HX1K-VQ100"])