File: test_cli_module.py

package info (click to toggle)
python-pyproject-parser 0.13.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,432 kB
  • sloc: python: 3,086; makefile: 5
file content (122 lines) | stat: -rw-r--r-- 3,793 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# stdlib
import collections
import email.headerregistry
import re
import sys
import warnings
from typing import Type

# 3rd party
import click
import pytest
from coincidence.regressions import AdvancedFileRegressionFixture
from consolekit.testing import CliRunner, Result
from consolekit.tracebacks import handle_tracebacks
from dom_toml.parser import BadConfigError
from domdf_python_tools.utils import redirect_output

# this package
from pyproject_parser.cli import ConfigTracebackHandler, prettify_deprecation_warning, resolve_class
from pyproject_parser.utils import PyProjectDeprecationWarning

exceptions = pytest.mark.parametrize(
		"exception",
		[
				pytest.param(FileNotFoundError("foo.txt"), id="FileNotFoundError"),
				pytest.param(FileExistsError("foo.txt"), id="FileExistsError"),
				pytest.param(Exception("Something's awry!"), id="Exception"),
				pytest.param(ValueError("'age' must be >= 0"), id="ValueError"),
				pytest.param(TypeError("Expected type int, got type str"), id="TypeError"),
				pytest.param(NameError("name 'hello' is not defined"), id="NameError"),
				pytest.param(SyntaxError("invalid syntax"), id="SyntaxError"),
				pytest.param(BadConfigError("Expected a string value for 'name'"), id="BadConfigError"),
				pytest.param(KeyError("name"), id="KeyError"),
				]
		)


@exceptions
def test_traceback_handler(
		exception: Exception,
		advanced_file_regression: AdvancedFileRegressionFixture,
		cli_runner: CliRunner,
		):

	@click.command()
	def demo():  # noqa: MAN002

		with handle_tracebacks(False, ConfigTracebackHandler):
			raise exception

	result: Result = cli_runner.invoke(demo, catch_exceptions=False)
	result.check_stdout(advanced_file_regression)
	assert result.exit_code == 1


@exceptions
def test_traceback_handler_show_traceback(exception: Exception, cli_runner: CliRunner):

	@click.command()
	def demo():  # noqa: MAN002

		with handle_tracebacks(True, ConfigTracebackHandler):
			raise exception

	with pytest.raises(type(exception), match=re.escape(str(exception))):
		cli_runner.invoke(demo, catch_exceptions=False)


@pytest.mark.parametrize("exception", [EOFError(), KeyboardInterrupt(), click.Abort()])
def test_handle_tracebacks_ignored_exceptions_click(
		exception: Exception,
		cli_runner: CliRunner,
		):

	@click.command()
	def demo():  # noqa: MAN002

		with handle_tracebacks(False, ConfigTracebackHandler):
			raise exception

	result: Result = cli_runner.invoke(demo, catch_exceptions=False)

	assert result.stdout.strip() == "Aborted!"
	assert result.exit_code == 1


@pytest.mark.parametrize("exception", [EOFError, KeyboardInterrupt, click.Abort, SystemExit])
def test_handle_tracebacks_ignored_exceptions(exception: Type[Exception]):

	with pytest.raises(exception):  # noqa: PT012
		with handle_tracebacks(False, ConfigTracebackHandler):
			raise exception


def test_resolve_class():
	# stdlib
	import importlib

	assert resolve_class("collections:defaultdict", "class") is collections.defaultdict
	assert resolve_class("importlib:import_module", "class") is importlib.import_module

	if sys.version_info >= (3, 8):
		# stdlib
		import importlib.metadata
		assert resolve_class("importlib.metadata:metadata", "class") is importlib.metadata.metadata

	assert resolve_class("email.headerregistry:Address", "class") is email.headerregistry.Address

	with pytest.raises(click.BadOptionUsage, match="Invalid syntax for '--class'") as e:
		resolve_class("collections.Counter", "class")

	assert e.value.option_name == "class"


@pytest.mark.filterwarnings("default")
def test_prettify_deprecation_warning():

	with redirect_output() as (stdout, stderr):
		prettify_deprecation_warning()
		warnings.warn("This is a warning", PyProjectDeprecationWarning)

	assert stderr.getvalue() == 'WARNING: This is a warning\n'