예제 #1
0
파일: lint.py 프로젝트: vr8hub/tools
def lint(plain_output: bool) -> int:
	"""
	Entry point for `se lint`
	"""

	parser = argparse.ArgumentParser(description="Check for various Standard Ebooks style errors.")
	parser.add_argument("-s", "--skip-lint-ignore", action="store_true", help="ignore rules in se-lint-ignore.xml file")
	parser.add_argument("-v", "--verbose", action="store_true", help="increase output verbosity")
	parser.add_argument("directories", metavar="DIRECTORY", nargs="+", help="a Standard Ebooks source directory")
	args = parser.parse_args()

	called_from_parallel = se.is_called_from_parallel(False)
	force_terminal = True if called_from_parallel else None # True will force colors, None will guess whether colors are enabled, False will disable colors
	first_output = True
	return_code = 0

	# Rich needs to know the terminal width in order to format tables.
	# If we're called from Parallel, there is no width because Parallel is not a terminal. Thus we must export $COLUMNS before
	# invoking Parallel, and then get that value here.
	console = Console(width=int(os.environ["COLUMNS"]) if called_from_parallel and "COLUMNS" in os.environ else None, highlight=False, theme=se.RICH_THEME, force_terminal=force_terminal) # Syntax highlighting will do weird things when printing paths; force_terminal prints colors when called from GNU Parallel

	for directory in args.directories:
		directory = Path(directory).resolve()
		messages = []
		exception = None
		table_data = []
		has_output = False

		try:
			se_epub = SeEpub(directory)
			messages = se_epub.lint(args.skip_lint_ignore)
		except se.SeException as ex:
			exception = ex
			if len(args.directories) > 1:
				return_code = se.LintFailedException.code
			else:
				return_code = ex.code

		# Print a separator newline if more than one table is printed
		if not first_output and (args.verbose or messages or exception):
			console.print("")
		elif first_output:
			first_output = False

		# Print the table header
		if ((len(args.directories) > 1 or called_from_parallel) and (messages or exception)) or args.verbose:
			has_output = True
			if plain_output:
				console.print(directory)
			else:
				console.print(f"[reverse][path][link=file://{directory}]{directory}[/][/][/reverse]")

		if exception:
			has_output = True
			se.print_error(exception, plain_output=plain_output)

		# Print the tables
		if messages:
			has_output = True
			return_code = se.LintFailedException.code

			if plain_output:
				for message in messages:
					label = "[Manual Review]"

					if message.message_type == se.MESSAGE_TYPE_ERROR:
						label = "[Error]"

					# Replace color markup with `
					message.text = se.prep_output(message.text, True)

					message_filename = ""
					if message.filename:
						message_filename = message.filename.name

					console.print(f"{message.code} {label} {message_filename} {message.text}")

					if message.submessages:
						for submessage in message.submessages:
							# Indent each line in case we have a multi-line submessage
							console.print(regex.sub(r"^", "\t", submessage, flags=regex.MULTILINE))
			else:
				for message in messages:
					alert = "[bright_yellow]Manual Review[/bright_yellow]"

					if message.message_type == se.MESSAGE_TYPE_ERROR:
						alert = "[bright_red]Error[/bright_red]"

					# Add hyperlinks around message filenames
					message_filename = ""
					if message.filename:
						message_filename = f"[link=file://{message.filename.resolve()}]{message.filename.name}[/link]"

					table_data.append([message.code, alert, message_filename, message.text])

					if message.submessages:
						for submessage in message.submessages:
							# Brackets don't need to be escaped in submessages if we instantiate them in Text()
							submessage_object = Text(submessage, style="dim")

							table_data.append([" ", " ", Text("→", justify="right"), submessage_object])

				table = Table(show_header=True, header_style="bold", show_lines=True, expand=True)
				table.add_column("Code", width=5, no_wrap=True)
				table.add_column("Severity", no_wrap=True)
				table.add_column("File", no_wrap=True)
				table.add_column("Message", ratio=10)

				for row in table_data:
					table.add_row(row[0], row[1], row[2], row[3])

				console.print(table)

		if args.verbose and not messages and not exception:
			if plain_output:
				console.print("OK")
			else:
				table = Table(show_header=False, box=box.SQUARE)
				table.add_column("", style="white on green4 bold")
				table.add_row("OK")
				console.print(table)

		# Print a newline if we're called from parallel and we just printed something, to
		# better visually separate output blocks
		if called_from_parallel and has_output:
			console.print("")

	return return_code
예제 #2
0
def lint() -> int:
    """
	Entry point for `se lint`
	"""

    parser = argparse.ArgumentParser(
        description="Check for various Standard Ebooks style errors.")
    parser.add_argument(
        "-p",
        "--plain",
        action="store_true",
        help="print plain text output, without tables or colors")
    parser.add_argument("-n",
                        "--no-colors",
                        dest="colors",
                        action="store_false",
                        help="do not use colored output")
    parser.add_argument("-s",
                        "--skip-lint-ignore",
                        action="store_true",
                        help="ignore rules in se-lint-ignore.xml file")
    parser.add_argument("-v",
                        "--verbose",
                        action="store_true",
                        help="increase output verbosity")
    parser.add_argument("directories",
                        metavar="DIRECTORY",
                        nargs="+",
                        help="a Standard Ebooks source directory")
    args = parser.parse_args()

    first_output = True
    return_code = 0

    for directory in args.directories:
        try:
            se_epub = SeEpub(directory)
            messages = se_epub.lint(args.skip_lint_ignore)
        except se.SeException as ex:
            se.print_error(ex)
            return ex.code

        table_data = []

        # Print a separator newline if more than one table is printed
        if not first_output and (args.verbose or messages):
            print("")
        elif first_output:
            first_output = False

        # Print the table header
        if args.verbose or (messages and len(args.directories) > 1):
            if args.plain:
                print(se_epub.path)
            else:
                print(stylize(str(se_epub.path), attr("reverse")))

        # Print the table
        if messages:
            return_code = se.LintFailedException.code

            if args.plain:
                for message in messages:
                    label = "Manual Review:"

                    if message.message_type == se.MESSAGE_TYPE_ERROR:
                        label = "Error:"

                    print(
                        f"{message.code} {label} {message.filename} {message.text}"
                    )

                    if message.submessages:
                        for submessage in message.submessages:
                            print(f"\t{submessage}")
            else:
                table_data.append([
                    stylize("Code", attr("bold")),
                    stylize("Severity", attr("bold")),
                    stylize("File", attr("bold")),
                    stylize("Message", attr("bold"))
                ])

                for message in messages:
                    alert = "Manual Review"

                    if message.message_type == se.MESSAGE_TYPE_ERROR:
                        alert = "Error"

                    message_text = message.text

                    if args.colors:
                        if message.message_type == se.MESSAGE_TYPE_ERROR:
                            alert = stylize(alert, fg("red"))
                        else:
                            alert = stylize(alert, fg("yellow"))

                        # By convention, any text within the message text that is surrounded in backticks
                        # is rendered in blue
                        message_text = regex.sub(
                            r"`(.+?)`", stylize(r"\1", fg("light_blue")),
                            message_text)

                    table_data.append(
                        [message.code, alert, message.filename, message_text])

                    if message.submessages:
                        for submessage in message.submessages:
                            table_data.append([" ", " ", "→", f"{submessage}"])

                _print_table(table_data, 3)

        if args.verbose and not messages:
            if args.plain:
                print("OK")
            else:
                table_data.append([
                    stylize(" OK ",
                            bg("green") + fg("white") + attr("bold"))
                ])

                _print_table(table_data)

    return return_code
예제 #3
0
def lint() -> int:
	"""
	Entry point for `se lint`
	"""

	from termcolor import colored

	parser = argparse.ArgumentParser(description="Check for various Standard Ebooks style errors.")
	parser.add_argument("-p", "--plain", action="store_true", help="print plain output")
	parser.add_argument("-v", "--verbose", action="store_true", help="increase output verbosity")
	parser.add_argument("directories", metavar="DIRECTORY", nargs="+", help="a Standard Ebooks source directory")
	args = parser.parse_args()

	first_output = True
	return_code = 0

	for directory in args.directories:
		try:
			se_epub = SeEpub(directory)
		except se.SeException as ex:
			se.print_error(ex)
			return ex.code

		messages = se_epub.lint()

		table_data = []

		# Print a separator newline if more than one table is printed
		if not first_output and (args.verbose or messages):
			print("")
		elif first_output:
			first_output = False

		# Print the table header
		if args.verbose or (messages and len(args.directories) > 1):
			if args.plain:
				print(se_epub.path)
			else:
				print(colored(se_epub.path, "white", attrs=["reverse"]))

		# Print the table
		if messages:
			return_code = se.LintFailedException.code

			if args.plain:
				for message in messages:
					if message.is_submessage:
						print("\t" + message.text)
					else:
						label = "Manual Review:"

						if message.message_type == se.MESSAGE_TYPE_ERROR:
							label = "Error:"

						print(label, message.filename, message.text)

			else:
				for message in messages:
					if message.is_submessage:
						table_data.append([" ", "→", "{}".format(message.text)])
					else:
						alert = colored("Manual Review", "yellow")

						if message.message_type == se.MESSAGE_TYPE_ERROR:
							alert = colored("Error", "red")

						table_data.append([alert, message.filename, message.text])

				se.print_table(table_data, 2)

		if args.verbose and not messages:
			if args.plain:
				print("OK")
			else:
				table_data.append([colored("OK", "green", attrs=["reverse"])])

				se.print_table(table_data)

	return return_code
예제 #4
0
def lint() -> int:
    """
	Entry point for `se lint`
	"""

    parser = argparse.ArgumentParser(
        description="Check for various Standard Ebooks style errors.")
    parser.add_argument("-n",
                        "--no-colors",
                        dest="colors",
                        action="store_false",
                        help="don’t use color or hyperlinks in output")
    parser.add_argument(
        "-p",
        "--plain",
        action="store_true",
        help="print plain text output, without tables or colors")
    parser.add_argument("-s",
                        "--skip-lint-ignore",
                        action="store_true",
                        help="ignore rules in se-lint-ignore.xml file")
    parser.add_argument("-v",
                        "--verbose",
                        action="store_true",
                        help="increase output verbosity")
    parser.add_argument("directories",
                        metavar="DIRECTORY",
                        nargs="+",
                        help="a Standard Ebooks source directory")
    args = parser.parse_args()

    called_from_parallel = se.is_called_from_parallel()
    first_output = True
    return_code = 0
    console = Console(
        highlight=False,
        theme=se.RICH_THEME,
        force_terminal=called_from_parallel
    )  # Syntax highlighting will do weird things when printing paths; force_terminal prints colors when called from GNU Parallel

    for directory in args.directories:
        directory = Path(directory).resolve()
        messages = []
        exception = None
        table_data = []
        has_output = False

        try:
            se_epub = SeEpub(directory)
            messages = se_epub.lint(args.skip_lint_ignore)
        except se.SeException as ex:
            exception = ex
            if len(args.directories) > 1:
                return_code = se.LintFailedException.code
            else:
                return_code = ex.code

        # Print a separator newline if more than one table is printed
        if not first_output and (args.verbose or messages or exception):
            console.print("")
        elif first_output:
            first_output = False

        # Print the table header
        if ((len(args.directories) > 1 or called_from_parallel) and
            (messages or exception)) or args.verbose:
            has_output = True
            if args.plain:
                console.print(directory)
            else:
                console.print(f"[reverse]{directory}[/reverse]")

        if exception:
            has_output = True
            se.print_error(exception)

        # Print the tables
        if messages:
            has_output = True
            return_code = se.LintFailedException.code

            if args.plain:
                for message in messages:
                    label = "Manual Review:"

                    if message.message_type == se.MESSAGE_TYPE_ERROR:
                        label = "Error:"

                    # Replace color markup with `
                    message.text = regex.sub(
                        r"\[(?:/|xhtml|xml|val|attr|val|class|path|url|text|bash|link)(?:=[^\]]*?)*\]",
                        "`", message.text)
                    message.text = regex.sub(r"`+", "`", message.text)

                    message_filename = ""
                    if message.filename:
                        message_filename = message.filename.name

                    console.print(
                        f"{message.code} {label} {message_filename} {message.text}"
                    )

                    if message.submessages:
                        for submessage in message.submessages:
                            # Indent each line in case we have a multi-line submessage
                            console.print(
                                regex.sub(r"^",
                                          "\t",
                                          submessage,
                                          flags=regex.MULTILINE))
            else:
                for message in messages:
                    alert = "Manual Review"

                    if message.message_type == se.MESSAGE_TYPE_ERROR:
                        alert = "Error"

                    message_text = message.text

                    if args.colors:
                        if message.message_type == se.MESSAGE_TYPE_ERROR:
                            alert = f"[bright_red]{alert}[/bright_red]"
                        else:
                            alert = f"[bright_yellow]{alert}[/bright_yellow]"

                        # Add hyperlinks around message filenames
                        message_filename = ""
                        if message.filename:
                            message_filename = f"[link=file://{message.filename.resolve()}]{message.filename.name}[/link]"
                    else:
                        # Replace color markup with `
                        message_text = regex.sub(
                            r"\[(?:/|xhtml|xml|val|attr|val|class|path|url|text|bash|link)(?:=[^\]]*?)*\]",
                            "`", message_text)
                        message_text = regex.sub(r"`+", "`", message_text)
                        message_filename = ""
                        if message.filename:
                            message_filename = message.filename.name

                    table_data.append(
                        [message.code, alert, message_filename, message_text])

                    if message.submessages:
                        for submessage in message.submessages:
                            # Brackets don't need to be escaped in submessages if we instantiate them in Text()
                            if args.colors:
                                submessage_object = Text(submessage,
                                                         style="dim")
                            else:
                                submessage_object = Text(submessage)

                            table_data.append([
                                " ", " ",
                                Text("→", justify="right"), submessage_object
                            ])

                table = Table(show_header=True,
                              header_style="bold",
                              show_lines=True)
                table.add_column("Code", width=5, no_wrap=True)
                table.add_column("Severity", no_wrap=True)
                table.add_column("File", no_wrap=True)
                table.add_column("Message")

                for row in table_data:
                    table.add_row(row[0], row[1], row[2], row[3])

                console.print(table)

        if args.verbose and not messages and not exception:
            if args.plain:
                console.print("OK")
            else:
                table = Table(show_header=False, box=box.SQUARE)
                table.add_column(
                    "", style="white on green4 bold" if args.colors else None)
                table.add_row("OK")
                console.print(table)

        # Print a newline if we're called from parallel and we just printed something, to
        # better visually separate output blocks
        if called_from_parallel and has_output:
            console.print("")

    return return_code