"""pytest command line options and fixtures."""

import pathlib
import platform as platform_

import pytest

DIRECTORY = pathlib.Path(__file__).parent

SKIP_EXE = '--skip-exe'


def pytest_addoption(parser):
    parser.addoption(SKIP_EXE, action='store_true',
                     help='skip tests with pytest.mark.exe;'
                          ' xfail tests with pytest.mark.exe(xfail=True)'
                          ' (tests that run Graphviz executables'
                          '  or subprocesses)')


def pytest_configure(config):
    config.addinivalue_line('markers',
                            f'exe(xfail): skip/xfail if {SKIP_EXE} is given')


def pytest_collection_modifyitems(config, items):
    if config.getoption(SKIP_EXE):
        def get_xfail(*, xfail: bool = False) -> bool:
            return xfail

        for item in items:
            exe_values = [get_xfail(*m.args, **m.kwargs)
                          for m in item.iter_markers(name='exe')]
            if exe_values:
                assert len(exe_values) == 1
                xfail, = exe_values
                if xfail:
                    marker = pytest.mark.xfail(reason=f'xfail by {SKIP_EXE} flag')
                else:
                    marker = pytest.mark.skip(reason=f'skipped by {SKIP_EXE} flag')
                item.add_marker(marker)


@pytest.fixture(scope='session')
def files_path():
    return DIRECTORY


@pytest.fixture(scope='session')
def platform():
    return platform_.system().lower()


@pytest.fixture(params=['darwin', 'freebsd', 'linux', 'windows'],
                ids=lambda p: f'platform={p!r}')
def mock_platform(monkeypatch, request):
    monkeypatch.setattr('graphviz.backend.viewing.PLATFORM', request.param)
    yield request.param


@pytest.fixture
def unknown_platform(monkeypatch, name='nonplatform'):
    monkeypatch.setattr('graphviz.backend.viewing.PLATFORM', name)
    yield name


@pytest.fixture
def run(mocker):  # noqa: N802
    yield mocker.patch('subprocess.run', autospec=True)


@pytest.fixture
def Popen(mocker):  # noqa: N802
    yield mocker.patch('subprocess.Popen', autospec=True)


@pytest.fixture
def startfile(mocker, platform):
    if platform == 'windows':
        kwargs = {'autospec': True}
    else:
        kwargs = {'create': True, 'new_callable': mocker.Mock}
    yield mocker.patch('os.startfile', **kwargs)


@pytest.fixture
def empty_path(monkeypatch):
    monkeypatch.setenv('PATH', '')


@pytest.fixture(params=[False, True], ids=lambda q: f'quiet={q!r}')
def quiet(request):
    return request.param


@pytest.fixture
def pipe(mocker):
    yield mocker.patch('graphviz.backend.piping.pipe', autospec=True)


@pytest.fixture
def pipe_lines(mocker):
    yield mocker.patch('graphviz.backend.piping.pipe_lines', autospec=True)


@pytest.fixture
def render(mocker):
    yield mocker.patch('graphviz.backend.rendering.render', autospec=True)

@@ -782,16 +782,26 @@
  = False
+, **kwargs
 ) -%3E boo
@@ -803,16 +803,52 @@
 %3E bool:%0A
+            kwargs%5B'xfail'%5D = xfail%0A
         
@@ -858,21 +858,22 @@
  return 
-xfail
+kwargs
 %0A%0A      
@@ -1103,21 +1103,22 @@
         
-xfail
+kwargs
 , = exe_
@@ -1143,21 +1143,31 @@
      if 
+kwargs%5B'
 xfail
+'%5D
 :%0A      
@@ -1184,42 +1184,36 @@
     
-marker = pytest.mark.xfail(
+kwargs.setdefault('
 reason
-=
+', 
 f'xf
@@ -1257,67 +1257,119 @@
     
-else:%0A                    marker = pytest.mark.skip(
+    marker = pytest.mark.xfail(**kwargs)%0A                else:%0A                    kwargs.setdefault('
 reason
-=
+', 
 f'sk
@@ -1387,32 +1387,88 @@
 KIP_EXE%7D flag')%0A
+                    marker = pytest.mark.skip(**kwargs)%0A
                 

allow passing keyword arguments such as raises though pytest.mark.exe