Repository: sphinx-extensions2/sphinx-pytest (language: python)

Issue:
Test failure with sphinx 7.2.3
With sphinx 7.2.3 I'm getting these test failures:

```xml
<?xml version="1.0" encoding="utf-8"?><testsuites><testsuite name="pytest" errors="0" failures="4" skipped="0" tests="4" time="0.340" timestamp="2023-08-26T12:02:22.347762" hostname="EDORAS"><testcase classname="tests.test_basic" name="test_basic" time="0.008"><failure message="AttributeError: 'path' object has no attribute 'mkdir'">sphinx_doctree = &lt;sphinx_pytest.plugin.CreateDoctree object at 0x00000151A3E7DFD0&gt;

    def test_basic(sphinx_doctree):
&gt;       result = sphinx_doctree("abc")

tests\test_basic.py:2: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src\sphinx_pytest\plugin.py:145: in __call__
    self._app_cls(
venv\Lib\site-packages\sphinx\testing\fixtures.py:183: in make
    app_: Any = SphinxTestApp(*args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = &lt;[AttributeError("'SphinxTestApp' object has no attribute 'builder'") raised in repr()] SphinxTestApp object at 0x151a3e7e110&gt;
buildername = 'doctree'
srcdir = path('C:\\Users\\Paul\\AppData\\Local\\Temp\\pytest-of-paul\\pytest-7\\test_basic0\\src')
builddir = path('C:\\Users\\Paul\\AppData\\Local\\Temp\\pytest-of-paul\\pytest-7\\test_basic0\\src\\_build')
freshenv = False, confoverrides = {}, status = &lt;_io.StringIO object at 0x00000151A3E38E50&gt;
warning = &lt;_io.StringIO object at 0x00000151A3E39240&gt;, tags = None, docutilsconf = None, parallel = 0

    def __init__(
        self,
        buildername: str = 'html',
        srcdir: _StrPath | None = None,
        builddir: _StrPath | None = None,
        freshenv: bool = False,
        confoverrides: dict | None = None,
        status: IO | None = None,
        warning: IO | None = None,
        tags: list[str] | None = None,
        docutilsconf: str | None = None,
        parallel: int = 0,
    ) -&gt; None:
        assert srcdir is not None
    
        self.docutils_conf_path = srcdir / 'docutils.conf'
        if docutilsconf is not None:
            self.docutils_conf_path.write_text(docutilsconf, encoding='utf8')
    
        if builddir is None:
            builddir = srcdir / '_build'
    
        confdir = srcdir
        outdir = builddir.joinpath(buildername)
&gt;       outdir.mkdir(parents=True, exist_ok=True)
E       AttributeError: 'path' object has no attribute 'mkdir'

venv\Lib\site-packages\sphinx\testing\util.py:106: AttributeError</failure></testcase><testcase classname="tests.test_basic" name="test_no_transforms" time="0.004"><failure message="AttributeError: 'path' object has no attribute 'mkdir'">sphinx_doctree_no_tr = &lt;sphinx_pytest.plugin.CreateDoctree object at 0x00000151A3F08C10&gt;

    def test_no_transforms(sphinx_doctree_no_tr):
        """Return the doctree, before any transforms have been applied."""
&gt;       result = sphinx_doctree_no_tr(".. _target:\n\nheader\n------\n")

tests\test_basic.py:11: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src\sphinx_pytest\plugin.py:145: in __call__
    self._app_cls(
venv\Lib\site-packages\sphinx\testing\fixtures.py:183: in make
    app_: Any = SphinxTestApp(*args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = &lt;[AttributeError("'SphinxTestApp' object has no attribute 'builder'") raised in repr()] SphinxTestApp object at 0x151a3f0b790&gt;
buildername = 'doctree'
srcdir = path('C:\\Users\\Paul\\AppData\\Local\\Temp\\pytest-of-paul\\pytest-7\\test_no_transforms0\\src')
builddir = path('C:\\Users\\Paul\\AppData\\Local\\Temp\\pytest-of-paul\\pytest-7\\test_no_transforms0\\src\\_build')
freshenv = False, confoverrides = {}, status = &lt;_io.StringIO object at 0x00000151A3F10820&gt;
warning = &lt;_io.StringIO object at 0x00000151A3F10D30&gt;, tags = None, docutilsconf = None, parallel = 0

    def __init__(
        self,
        buildername: str = 'html',
        srcdir: _StrPath | None = None,
        builddir: _StrPath | None = None,
        freshenv: bool = False,
        confoverrides: dict | None = None,
        status: IO | None = None,
        warning: IO | None = None,
        tags: list[str] | None = None,
        docutilsconf: str | None = None,
        parallel: int = 0,
    ) -&gt; None:
        assert srcdir is not None
    
        self.docutils_conf_path = srcdir / 'docutils.conf'
        if docutilsconf is not None:
            self.docutils_conf_path.write_text(docutilsconf, encoding='utf8')
    
        if builddir is None:
            builddir = srcdir / '_build'
    
        confdir = srcdir
        outdir = builddir.joinpath(buildername)
&gt;       outdir.mkdir(parents=True, exist_ok=True)
E       AttributeError: 'path' object has no attribute 'mkdir'

venv\Lib\site-packages\sphinx\testing\util.py:106: AttributeError</failure></testcase><testcase classname="tests.test_basic" name="test_with_transforms" time="0.003"><failure message="AttributeError: 'path' object has no attribute 'mkdir'">sphinx_doctree = &lt;sphinx_pytest.plugin.CreateDoctree object at 0x00000151A3EE1210&gt;

    def test_with_transforms(sphinx_doctree):
        """Return the doctree, after transforms (but not post-transforms)."""
&gt;       result = sphinx_doctree(".. _target:\n\nheader\n------\n")

tests\test_basic.py:26: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src\sphinx_pytest\plugin.py:145: in __call__
    self._app_cls(
venv\Lib\site-packages\sphinx\testing\fixtures.py:183: in make
    app_: Any = SphinxTestApp(*args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = &lt;[AttributeError("'SphinxTestApp' object has no attribute 'builder'") raised in repr()] SphinxTestApp object at 0x151a3ee27d0&gt;
buildername = 'doctree'
srcdir = path('C:\\Users\\Paul\\AppData\\Local\\Temp\\pytest-of-paul\\pytest-7\\test_with_transforms0\\src')
builddir = path('C:\\Users\\Paul\\AppData\\Local\\Temp\\pytest-of-paul\\pytest-7\\test_with_transforms0\\src\\_build')
freshenv = False, confoverrides = {}, status = &lt;_io.StringIO object at 0x00000151A3E39240&gt;
warning = &lt;_io.StringIO object at 0x00000151A3F10940&gt;, tags = None, docutilsconf = None, parallel = 0

    def __init__(
        self,
        buildername: str = 'html',
        srcdir: _StrPath | None = None,
        builddir: _StrPath | None = None,
        freshenv: bool = False,
        confoverrides: dict | None = None,
        status: IO | None = None,
        warning: IO | None = None,
        tags: list[str] | None = None,
        docutilsconf: str | None = None,
        parallel: int = 0,
    ) -&gt; None:
        assert srcdir is not None
    
        self.docutils_conf_path = srcdir / 'docutils.conf'
        if docutilsconf is not None:
            self.docutils_conf_path.write_text(docutilsconf, encoding='utf8')
    
        if builddir is None:
            builddir = srcdir / '_build'
    
        confdir = srcdir
        outdir = builddir.joinpath(buildername)
&gt;       outdir.mkdir(parents=True, exist_ok=True)
E       AttributeError: 'path' object has no attribute 'mkdir'

venv\Lib\site-packages\sphinx\testing\util.py:106: AttributeError</failure></testcase><testcase classname="tests.test_basic" name="test_html_builder" time="0.003"><failure message="AttributeError: 'path' object has no attribute 'mkdir'">sphinx_doctree = &lt;sphinx_pytest.plugin.CreateDoctree object at 0x00000151A3F89E10&gt;

    def test_html_builder(sphinx_doctree):
        sphinx_doctree.buildername = "html"
&gt;       result = sphinx_doctree(".. only:: html\n\n   abc\n\n.. only:: latex\n\n   xyz\n")

tests\test_basic.py:41: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src\sphinx_pytest\plugin.py:145: in __call__
    self._app_cls(
venv\Lib\site-packages\sphinx\testing\fixtures.py:183: in make
    app_: Any = SphinxTestApp(*args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = &lt;[AttributeError("'SphinxTestApp' object has no attribute 'builder'") raised in repr()] SphinxTestApp object at 0x151a3f88c50&gt;
buildername = 'html'
srcdir = path('C:\\Users\\Paul\\AppData\\Local\\Temp\\pytest-of-paul\\pytest-7\\test_html_builder0\\src')
builddir = path('C:\\Users\\Paul\\AppData\\Local\\Temp\\pytest-of-paul\\pytest-7\\test_html_builder0\\src\\_build')
freshenv = False, confoverrides = {}, status = &lt;_io.StringIO object at 0x00000151A3F10DC0&gt;
warning = &lt;_io.StringIO object at 0x00000151A3F11000&gt;, tags = None, docutilsconf = None, parallel = 0

    def __init__(
        self,
        buildername: str = 'html',
        srcdir: _StrPath | None = None,
        builddir: _StrPath | None = None,
        freshenv: bool = False,
        confoverrides: dict | None = None,
        status: IO | None = None,
        warning: IO | None = None,
        tags: list[str] | None = None,
        docutilsconf: str | None = None,
        parallel: int = 0,
    ) -&gt; None:
        assert srcdir is not None
    
        self.docutils_conf_path = srcdir / 'docutils.conf'
        if docutilsconf is not None:
            self.docutils_conf_path.write_text(docutilsconf, encoding='utf8')
    
        if builddir is None:
            builddir = srcdir / '_build'
    
        confdir = srcdir
        outdir = builddir.joinpath(buildername)
&gt;       outdir.mkdir(parents=True, exist_ok=True)
E       AttributeError: 'path' object has no attribute 'mkdir'

venv\Lib\site-packages\sphinx\testing\util.py:106: AttributeError</failure></testcase></testsuite></testsuites>
```


Discussion / hints:

Fix patch:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 5e2fd02..7c1b37b 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -41,5 +41,5 @@ repos:
       args: [--config-file=pyproject.toml]
       additional_dependencies:
       - types-docutils
-      - sphinx~=4.1
+      - sphinx~=7.0
       - pytest


Test patch:
diff --git a/src/sphinx_pytest/plugin.py b/src/sphinx_pytest/plugin.py
index 1a1a5c0..c6363f7 100644
--- a/src/sphinx_pytest/plugin.py
+++ b/src/sphinx_pytest/plugin.py
@@ -9,8 +9,8 @@
 from docutils import nodes
 from docutils.core import Publisher
 import pytest
+from sphinx import version_info as sphinx_version_info
 from sphinx.environment import BuildEnvironment
-from sphinx.testing.path import path
 from sphinx.testing.util import SphinxTestApp
 
 from .builders import DoctreeBuilder
@@ -90,12 +90,22 @@ def doctrees(self) -> dict[str, nodes.document] | Doctrees:
         except AttributeError:
             return Doctrees(self.env)
 
-    def pformat(self, docname: str = "index") -> str:
+    def pformat(
+        self, docname: str = "index", pop_doc_attrs=("translation_progress",)
+    ) -> str:
         """Return an indented pseudo-XML representation.
 
         The src directory is replaced with <src>, for reproducibility.
+
+        :param pop_doc_attrs: Remove these attributes of the doctree node,
+            before converting to text.
+            By default, ``translation_progress`` is removed for compatibility
+            (added in sphinx 7.1).
         """
-        text = self.doctrees[docname].pformat()
+        doctree = self.doctrees[docname].deepcopy()
+        for attr_name in pop_doc_attrs:
+            doctree.attributes.pop(attr_name, None)
+        text = doctree.pformat()
         return text.replace(str(self._app.srcdir) + os.sep, "<src>/").rstrip()
 
     def get_resolved_doctree(self, docname: str = "index") -> nodes.document:
@@ -109,9 +119,22 @@ def get_resolved_doctree(self, docname: str = "index") -> nodes.document:
         # https://github.com/sphinx-doc/sphinx/blob/05a898ecb4ff8e654a053a1ba5131715a4514812/sphinx/environment/__init__.py#L538
         return doctree
 
-    def get_resolved_pformat(self, docname: str = "index") -> str:
-        """Return the pformat of the doctree after post-transforms."""
-        text = self.get_resolved_doctree(docname).pformat()
+    def get_resolved_pformat(
+        self, docname: str = "index", pop_doc_attrs=("translation_progress",)
+    ) -> str:
+        """Return an indented pseudo-XML representation, after post-transforms.
+
+        The src directory is replaced with <src>, for reproducibility.
+
+        :param pop_doc_attrs: Remove these attributes of the doctree node,
+            before converting to text.
+            By default, ``translation_progress`` is removed for compatibility
+            (added in sphinx 7.1).
+        """
+        doctree = self.get_resolved_doctree(docname)
+        for attr_name in pop_doc_attrs:
+            doctree.attributes.pop(attr_name, None)
+        text = doctree.pformat()
         return text.replace(str(self._app.srcdir) + os.sep, "<src>/").rstrip()
 
 
@@ -141,9 +164,17 @@ def __call__(
         self.srcdir.joinpath(filename).parent.mkdir(parents=True, exist_ok=True)
         self.srcdir.joinpath(filename).write_text(content, encoding="utf8")
 
+        srcdir: Any
+        if sphinx_version_info >= (7, 2):
+            srcdir = self.srcdir
+        else:
+            from sphinx.testing.path import path
+
+            srcdir = path(str(self.srcdir))
+
         return AppWrapper(
             self._app_cls(
-                srcdir=path(str(self.srcdir)),
+                srcdir=srcdir,
                 buildername=self.buildername,
                 confoverrides=self._confoverrides,
                 **kwargs,