sphinx-contrib / spelling

A spelling checker for Sphinx-based documentation
https://sphinxcontrib-spelling.readthedocs.io/en/latest/
BSD 2-Clause "Simplified" License
82 stars 47 forks source link

7.6.0: pytest is faioing in few units #186

Closed kloczek closed 2 years ago

kloczek commented 2 years ago

I'm packaging your module as an rpm package so I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.

Here is pytest output:

```console + PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-sphinxcontrib-spelling-7.6.0-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-sphinxcontrib-spelling-7.6.0-2.fc35.x86_64/usr/lib/python3.8/site-packages + /usr/bin/pytest -ra =========================================================================== test session starts ============================================================================ platform linux -- Python 3.8.13, pytest-7.1.2, pluggy-1.0.0 rootdir: /home/tkloczko/rpmbuild/BUILD/spelling-7.6.0 collected 62 items tests/test_builder.py ...F......F....FFFF [ 30%] tests/test_checker.py FFFF.. [ 40%] tests/test_filter.py ....sssssssssssssssssssssssssss...... [100%] ================================================================================= FAILURES ================================================================================= ___________________________________________________________________________ test_ignore_literals ___________________________________________________________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-918/test_ignore_literals0/src'), local('/tmp/pytest-of-tkloczko/pytest-918/test_ignore_literals0/out')) def test_ignore_literals(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' Welcome to Spelling Checker documentation! ========================================== There are several misspelled words in this text. :: Literal blocks are ignoreed. Inline ``litterals`` are ignored, too. ''') stdout, stderr, output_text = get_sphinx_output(srcdir, outdir, 'contents') # The 'contents.spelling' output file should not have been # created, because the errors are ignored. > assert output_text is None E AssertionError: assert '../../../../../tmp/pytest-of-tkloczko/pytest-918/test_ignore_literals0/src/contents.rst:3: (Welcome) Welcome to Spel..../../../../../tmp/pytest-of-tkloczko/pytest-918/test_ignore_literals0/src/contents.rst:11: (too) are ignored, too.\n' is None tests/test_builder.py:135: AssertionError --------------------------------------------------------------------------- Captured stderr call --------------------------------------------------------------------------- fatal: not a git repository (or any parent up to mount point /home/tkloczko) Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). ---------------------------------------------------------------------------- Captured log call ----------------------------------------------------------------------------- WARNING test.filters:filters.py:249 Called: git log --quiet --no-color --pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn WARNING test.filters:filters.py:250 Failed to scan contributors: Command '['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn']' returned non-zero exit status 128. _____________________________________________________________________________ test_docstrings ______________________________________________________________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-918/test_docstrings0/src'), local('/tmp/pytest-of-tkloczko/pytest-918/test_docstrings0/out')) def test_docstrings(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'conf.py', ''' extensions = ['sphinxcontrib.spelling', 'sphinx.ext.autodoc'] ''') add_file(srcdir / '..', 'the_source.py', ''' #!/usr/bin/env python3 def public_function(arg_name): """Does something useful. :param arg_name: Pass a vaule """ return 1 ''') add_file(srcdir, 'contents.rst', ''' The Module ========== .. automodule:: the_source :members: ''') with working_dir(srcdir / '..'): with import_path(['.'] + sys.path): stdout, stderr, output_text = get_sphinx_output( srcdir, outdir, 'contents', ) # Expected string is too long for one line expected = ( 'the_source.py:' 'docstring of the_source.public_function:' 'None:' ' (vaule)' ) > assert expected in output_text E AssertionError: assert 'the_source.py:docstring of the_source.public_function:None: (vaule)' in 'src/contents.rst:3: (The) The Module\nsrc/contents.rst:3: (Module) The Module\nthe_source.py:docstring of the_sourc...public_function:1: (a) Pass a vaule\nthe_source.py:docstring of the_source.public_function:1: (vaule) Pass a vaule\n' tests/test_builder.py:296: AssertionError --------------------------------------------------------------------------- Captured stderr call --------------------------------------------------------------------------- fatal: not a git repository (or any parent up to mount point /) Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). ---------------------------------------------------------------------------- Captured log call ----------------------------------------------------------------------------- WARNING test.filters:filters.py:249 Called: git log --quiet --no-color --pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn WARNING test.filters:filters.py:250 Failed to scan contributors: Command '['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn']' returned non-zero exit status 128. __________________________________________________________________________ test_legacy_directive ___________________________________________________________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-918/test_legacy_directive0/src'), local('/tmp/pytest-of-tkloczko/pytest-918/test_legacy_directive0/out')) def test_legacy_directive(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' The Module ========== .. spelling:: teh teh is OK ''') stdout, stderr, output_text = get_sphinx_output( srcdir, outdir, 'contents', ) > assert output_text is None E AssertionError: assert '../../../../../tmp/pytest-of-tkloczko/pytest-918/test_legacy_directive0/src/contents.rst:3: (The) The Module\n../../... Module\n../../../../../tmp/pytest-of-tkloczko/pytest-918/test_legacy_directive0/src/contents.rst:9: (is) teh is OK\n' is None tests/test_builder.py:376: AssertionError --------------------------------------------------------------------------- Captured stdout call --------------------------------------------------------------------------- contents ['teh'] --------------------------------------------------------------------------- Captured stderr call --------------------------------------------------------------------------- fatal: not a git repository (or any parent up to mount point /home/tkloczko) Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). ---------------------------------------------------------------------------- Captured log call ----------------------------------------------------------------------------- WARNING test.filters:filters.py:249 Called: git log --quiet --no-color --pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn WARNING test.filters:filters.py:250 Failed to scan contributors: Command '['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn']' returned non-zero exit status 128. __________________________________________________________________________ test_domain_directive ___________________________________________________________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-918/test_domain_directive0/src'), local('/tmp/pytest-of-tkloczko/pytest-918/test_domain_directive0/out')) def test_domain_directive(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' The Module ========== .. spelling:word-list:: teh teh is OK ''') stdout, stderr, output_text = get_sphinx_output( srcdir, outdir, 'contents', ) > assert output_text is None E AssertionError: assert '../../../../../tmp/pytest-of-tkloczko/pytest-918/test_domain_directive0/src/contents.rst:3: (The) The Module\n../../... Module\n../../../../../tmp/pytest-of-tkloczko/pytest-918/test_domain_directive0/src/contents.rst:9: (is) teh is OK\n' is None tests/test_builder.py:399: AssertionError --------------------------------------------------------------------------- Captured stdout call --------------------------------------------------------------------------- contents ['teh'] --------------------------------------------------------------------------- Captured stderr call --------------------------------------------------------------------------- fatal: not a git repository (or any parent up to mount point /home/tkloczko) Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). ---------------------------------------------------------------------------- Captured log call ----------------------------------------------------------------------------- WARNING test.filters:filters.py:249 Called: git log --quiet --no-color --pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn WARNING test.filters:filters.py:250 Failed to scan contributors: Command '['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn']' returned non-zero exit status 128. _____________________________________________________________________________ test_domain_role _____________________________________________________________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-918/test_domain_role0/src'), local('/tmp/pytest-of-tkloczko/pytest-918/test_domain_role0/out')) def test_domain_role(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' The Module ========== :spelling:word:`teh` is OK ''') stdout, stderr, output_text = get_sphinx_output( srcdir, outdir, 'contents', ) > assert output_text is None E AssertionError: assert '../../../../../tmp/pytest-of-tkloczko/pytest-918/test_domain_role0/src/contents.rst:3: (The) The Module\n../../../.....ling:word:`teh`\n../../../../../tmp/pytest-of-tkloczko/pytest-918/test_domain_role0/src/contents.rst:5: (is) is OK\n' is None tests/test_builder.py:418: AssertionError --------------------------------------------------------------------------- Captured stdout call --------------------------------------------------------------------------- contents ['teh'] --------------------------------------------------------------------------- Captured stderr call --------------------------------------------------------------------------- fatal: not a git repository (or any parent up to mount point /home/tkloczko) Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). ---------------------------------------------------------------------------- Captured log call ----------------------------------------------------------------------------- WARNING test.filters:filters.py:249 Called: git log --quiet --no-color --pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn WARNING test.filters:filters.py:250 Failed to scan contributors: Command '['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn']' returned non-zero exit status 128. _____________________________________________________________________ test_domain_role_multiple_words ______________________________________________________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-918/test_domain_role_multiple_word0/src'), local('/tmp/pytest-of-tkloczko/pytest-918/test_domain_role_multiple_word0/out')) def test_domain_role_multiple_words(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' The Module ========== :spelling:word:`teh is KO` ''') stdout, stderr, output_text = get_sphinx_output( srcdir, outdir, 'contents', ) > assert output_text is None E AssertionError: assert '../../../../../tmp/pytest-of-tkloczko/pytest-918/test_domain_role_multiple_word0/src/contents.rst:3: (The) The Modul...pytest-of-tkloczko/pytest-918/test_domain_role_multiple_word0/src/contents.rst:5: (word) :spelling:word:`teh is KO`\n' is None tests/test_builder.py:437: AssertionError --------------------------------------------------------------------------- Captured stdout call --------------------------------------------------------------------------- contents ['teh', 'is', 'KO'] --------------------------------------------------------------------------- Captured stderr call --------------------------------------------------------------------------- fatal: not a git repository (or any parent up to mount point /home/tkloczko) Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). ---------------------------------------------------------------------------- Captured log call ----------------------------------------------------------------------------- WARNING test.filters:filters.py:249 Called: git log --quiet --no-color --pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn WARNING test.filters:filters.py:250 Failed to scan contributors: Command '['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn']' returned non-zero exit status 128. _____________________________________________________________________________ test_errors_only _____________________________________________________________________________ def test_errors_only(): checker = SpellingChecker(lang='en_US', suggest=False, word_list_filename=None, ) for word, suggestions, line, offset in checker.check('This txt is wrong'): assert not suggestions, 'Suggesting' > assert word == 'txt' E AssertionError: assert 'This' == 'txt' E - txt E + This tests/test_checker.py:19: AssertionError __________________________________________________________________________ test_with_suggestions ___________________________________________________________________________ def test_with_suggestions(): checker = SpellingChecker(lang='en_US', suggest=True, word_list_filename=None, ) for word, suggestions, line, offset in checker.check('This txt is wrong'): > assert suggestions, 'Not suggesting' E AssertionError: Not suggesting E assert [] tests/test_checker.py:30: AssertionError ____________________________________________________________________________ test_with_wordlist ____________________________________________________________________________ def test_with_wordlist(): checker = SpellingChecker( lang='en_US', suggest=False, word_list_filename=os.path.join(os.path.dirname(__file__), 'test_wordlist.txt') ) words = [w for w, s, l, o in checker.check('This txt is wrong')] > assert not words, 'Did not use personal word list file' E AssertionError: Did not use personal word list file E assert not ['This', 'is', 'wrong'] tests/test_checker.py:43: AssertionError __________________________________________________________________________ test_with_context_line __________________________________________________________________________ def test_with_context_line(): checker = SpellingChecker(lang='en_US', suggest=False, word_list_filename=None, context_line=True, ) text = 'Line one\nThis txt is wrong\nLine two' for word, suggestions, line, offset in checker.check(text): assert not suggestions, 'Suggesting' > assert word == 'txt' E AssertionError: assert 'Line' == 'txt' E - txt E + Line tests/test_checker.py:56: AssertionError ============================================================================= warnings summary ============================================================================= tests/test_builder.py: 10 warnings /home/tkloczko/rpmbuild/BUILD/spelling-7.6.0/sphinxcontrib/spelling/builder.py:217: PendingDeprecationWarning: nodes.Node.traverse() is obsoleted by Node.findall(). for node in doctree.traverse(docutils.nodes.Text): tests/test_builder.py::test_domain_role tests/test_builder.py::test_domain_role_multiple_words /usr/lib/python3.8/site-packages/docutils/parsers/rst/roles.py:205: DeprecationWarning: nodes.Text: initialization argument "rawsource" is ignored and will be removed in Docutils 1.3. return [self.node_class(rawtext, text, **options)], [] -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html ========================================================================= short test summary info ========================================================================== SKIPPED [27] tests/test_filter.py:49: Not a git repo FAILED tests/test_builder.py::test_ignore_literals - AssertionError: assert '../../../../../tmp/pytest-of-tkloczko/pytest-918/test_ignore_literals0/src/contents.rst:3: (... FAILED tests/test_builder.py::test_docstrings - AssertionError: assert 'the_source.py:docstring of the_source.public_function:None: (vaule)' in 'src/contents.rst:3: (The... FAILED tests/test_builder.py::test_legacy_directive - AssertionError: assert '../../../../../tmp/pytest-of-tkloczko/pytest-918/test_legacy_directive0/src/contents.rst:3:... FAILED tests/test_builder.py::test_domain_directive - AssertionError: assert '../../../../../tmp/pytest-of-tkloczko/pytest-918/test_domain_directive0/src/contents.rst:3:... FAILED tests/test_builder.py::test_domain_role - AssertionError: assert '../../../../../tmp/pytest-of-tkloczko/pytest-918/test_domain_role0/src/contents.rst:3: (The) Th... FAILED tests/test_builder.py::test_domain_role_multiple_words - AssertionError: assert '../../../../../tmp/pytest-of-tkloczko/pytest-918/test_domain_role_multiple_word0/... FAILED tests/test_checker.py::test_errors_only - AssertionError: assert 'This' == 'txt' FAILED tests/test_checker.py::test_with_suggestions - AssertionError: Not suggesting FAILED tests/test_checker.py::test_with_wordlist - AssertionError: Did not use personal word list file FAILED tests/test_checker.py::test_with_context_line - AssertionError: assert 'Line' == 'txt' ========================================================== 10 failed, 25 passed, 27 skipped, 12 warnings in 1.42s ========================================================== ```

Here is list of installed modules in build env

```console Package Version ----------------------------- ----------------- alabaster 0.7.12 attrs 22.1.0 Babel 2.10.2 Brlapi 0.8.3 build 0.8.0 charset-normalizer 2.1.0 codespell 2.1.0 cycler 0.11.0 distro 1.7.0 docutils 0.18.1 extras 1.0.0 fixtures 4.0.0 fonttools 4.37.1 gpg 1.17.1-unknown idna 3.3 imagesize 1.4.1 importlib-metadata 4.12.0 iniconfig 1.1.1 Jinja2 3.1.1 kiwisolver 1.4.4 libcomps 0.1.18 louis 3.22.0 MarkupSafe 2.1.1 matplotlib 3.5.3 numpy 1.23.1 olefile 0.46 packaging 21.3 pbr 5.9.0 pep517 0.12.0 Pillow 9.2.0 pip 22.2.1 pluggy 1.0.0 py 1.11.0 pyenchant 3.2.2 Pygments 2.13.0 PyGObject 3.42.2 pyparsing 3.0.9 pytest 7.1.2 python-dateutil 2.8.2 pytz 2022.1 requests 2.28.1 rpm 4.17.0 setuptools 65.3.0 six 1.16.0 snowballstemmer 2.2.0 Sphinx 5.1.1 sphinxcontrib-applehelp 1.0.2.dev20220730 sphinxcontrib-devhelp 1.0.2.dev20220730 sphinxcontrib-htmlhelp 2.0.0 sphinxcontrib-jsmath 1.0.1.dev20220730 sphinxcontrib-qthelp 1.0.3.dev20220730 sphinxcontrib-serializinghtml 1.1.5 sphinxcontrib-spelling 7.5.0 testtools 2.5.0 tomli 2.0.1 urllib3 1.26.12 wheel 0.37.1 zipp 3.8.1 ```
dhellmann commented 2 years ago

The changes in #187 should ensure this works. Let me know if there's still an issue.

kloczek commented 1 year ago

Just tested 7.7.0 and test suite still fails. I'm using latest sphinx 6.1.3 Here is pytest output:

```console + PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-sphinxcontrib-spelling-7.7.0-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-sphinxcontrib-spelling-7.7.0-2.fc35.x86_64/usr/lib/python3.8/site-packages + /usr/bin/pytest -ra -m 'not network' ============================= test session starts ============================== platform linux -- Python 3.8.16, pytest-7.2.1, pluggy-1.0.0 rootdir: /home/tkloczko/rpmbuild/BUILD/spelling-7.7.0 collected 66 items tests/test_builder.py FFFFFFFFFFsFFFFFFFF.FF. [ 34%] tests/test_checker.py FFFF.. [ 43%] tests/test_filter.py ....sssssssssssssssssssssssssss...... [100%] =================================== FAILURES =================================== __________________________________ test_setup __________________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_setup0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_setup0/out')) def test_setup(sphinx_project): srcdir, outdir = sphinx_project stdout = io.StringIO() stderr = io.StringIO() # If the spelling builder is not properly initialized, # trying to use it with the Sphinx app class will # generate an exception. > Sphinx( str(srcdir), str(srcdir), str(outdir), str(outdir), 'spelling', status=stdout, warning=stderr, freshenv=True, ) tests/test_builder.py:90: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError __________________________________ test_title __________________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_title0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_title0/out')) def test_title(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' Welcome to Speeling Checker documentation! ========================================== ''') > stdout, stderr, output_text = get_sphinx_output(srcdir, outdir, 'contents') tests/test_builder.py:103: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:72: in get_sphinx_output stdout, stderr, app = get_sphinx_app(srcdir, outdir, docname, builder) tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError __________________________________ test_body ___________________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_body0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_body0/out')) def test_body(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' Welcome to Spelling Checker documentation! ========================================== There are several mispelled words in this txt. ''') > stdout, stderr, output_text = get_sphinx_output(srcdir, outdir, 'contents') tests/test_builder.py:115: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:72: in get_sphinx_output stdout, stderr, app = get_sphinx_app(srcdir, outdir, docname, builder) tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError _____________________________ test_ignore_literals _____________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_ignore_literals0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_ignore_literals0/out')) def test_ignore_literals(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' Welcome to Spelling Checker documentation! ========================================== There are several misspelled words in this text. :: Literal blocks are ignoreed. Inline ``litterals`` are ignored, too. ''') > stdout, stderr, output_text = get_sphinx_output(srcdir, outdir, 'contents') tests/test_builder.py:135: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:72: in get_sphinx_output stdout, stderr, app = get_sphinx_app(srcdir, outdir, docname, builder) tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError ___________________________ test_several_word_lists ____________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_several_word_lists0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_several_word_lists0/out')) def test_several_word_lists(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'conf.py', ''' extensions = ['sphinxcontrib.spelling'] spelling_word_list_filename=['test_wordlist.txt','test_wordlist2.txt'] ''') add_file(srcdir, 'contents.rst', ''' Welcome to Spelling Checker documentation! ========================================== There are several mispelled words in tihs txt. ''') add_file(srcdir, 'test_wordlist.txt', ''' txt ''') add_file(srcdir, 'test_wordlist2.txt', ''' mispelled ''') > stdout, stderr, output_text = get_sphinx_output(srcdir, outdir, 'contents') tests/test_builder.py:162: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:72: in get_sphinx_output stdout, stderr, app = get_sphinx_app(srcdir, outdir, docname, builder) tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError ____________________________ test_word_list_default ____________________________ tmpdir = local('/tmp/pytest-of-tkloczko/pytest-179/test_word_list_default0') def test_word_list_default(tmpdir): > srcdir, outdir, stdout, stderr, app = _wordlist_sphinx_project( tmpdir, ''' extensions = ['sphinxcontrib.spelling'] ''', ) tests/test_builder.py:184: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:179: in _wordlist_sphinx_project stdout, stderr, app = get_sphinx_app(srcdir, outdir, 'contents') tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError ____________________________ test_one_word_list_str ____________________________ tmpdir = local('/tmp/pytest-of-tkloczko/pytest-179/test_one_word_list_str0') def test_one_word_list_str(tmpdir): > srcdir, outdir, stdout, stderr, app = _wordlist_sphinx_project( tmpdir, ''' extensions = ['sphinxcontrib.spelling'] spelling_word_list_filename='test_wordlist.txt' ''', ) tests/test_builder.py:196: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:179: in _wordlist_sphinx_project stdout, stderr, app = get_sphinx_app(srcdir, outdir, 'contents') tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError _________________________ test_multiple_word_list_str __________________________ tmpdir = local('/tmp/pytest-of-tkloczko/pytest-179/test_multiple_word_list_str0') def test_multiple_word_list_str(tmpdir): # We don't expect anyone to set up their conf.py this way but it # simulates passing the configuration option from the command line # using -D. > srcdir, outdir, stdout, stderr, app = _wordlist_sphinx_project( tmpdir, ''' extensions = ['sphinxcontrib.spelling'] spelling_word_list_filename='test_wordlist.txt,test_wordlist2.txt' ''', ) tests/test_builder.py:212: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:179: in _wordlist_sphinx_project stdout, stderr, app = get_sphinx_app(srcdir, outdir, 'contents') tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError _________________________ test_multiple_word_list_list _________________________ tmpdir = local('/tmp/pytest-of-tkloczko/pytest-179/test_multiple_word_list_list0') def test_multiple_word_list_list(tmpdir): > srcdir, outdir, stdout, stderr, app = _wordlist_sphinx_project( tmpdir, ''' extensions = ['sphinxcontrib.spelling'] spelling_word_list_filename=['test_wordlist.txt', 'test_wordlist2.txt'] ''', ) tests/test_builder.py:226: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:179: in _wordlist_sphinx_project stdout, stderr, app = get_sphinx_app(srcdir, outdir, 'contents') tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError _______________________________ test_ignore_file _______________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_ignore_file0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_ignore_file0/out')) def test_ignore_file(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'conf.py', ''' extensions = ['sphinxcontrib.spelling'] spelling_exclude_patterns=['con*'] ''') add_file(srcdir, 'contents.rst', ''' Welcome to Speeling Checker documentation! ========================================== ''') > stdout, stderr, output_text = get_sphinx_output(srcdir, outdir, 'contents') tests/test_builder.py:251: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:72: in get_sphinx_output stdout, stderr, app = get_sphinx_app(srcdir, outdir, docname, builder) tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError _______________________ test_get_suggestions_to_show_all _______________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_get_suggestions_to_show_a0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_get_suggestions_to_show_a0/out')) def test_get_suggestions_to_show_all(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'conf.py', ''' extensions = ['sphinxcontrib.spelling'] spelling_show_suggestions = True spelling_suggestion_limit = 0 ''') > stdout, stderr, app = get_sphinx_app(srcdir, outdir, 'contents') tests/test_builder.py:316: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError ______________________ test_get_suggestions_to_show_limit ______________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_get_suggestions_to_show_l0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_get_suggestions_to_show_l0/out')) def test_get_suggestions_to_show_limit(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'conf.py', ''' extensions = ['sphinxcontrib.spelling'] spelling_show_suggestions = True spelling_suggestion_limit = 1 ''') > stdout, stderr, app = get_sphinx_app(srcdir, outdir, 'contents') tests/test_builder.py:328: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError ____________________ test_get_suggestions_to_show_disabled _____________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_get_suggestions_to_show_d0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_get_suggestions_to_show_d0/out')) def test_get_suggestions_to_show_disabled(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'conf.py', ''' extensions = ['sphinxcontrib.spelling'] spelling_show_suggestions = False spelling_suggestion_limit = 0 ''') > stdout, stderr, app = get_sphinx_app(srcdir, outdir, 'contents') tests/test_builder.py:340: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError ________________________________ test_captions _________________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_captions0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_captions0/out')) def test_captions(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' The Module ========== .. figure:: blah.gif Teh caption ''') > stdout, stderr, output_text = get_sphinx_output( srcdir, outdir, 'contents', ) tests/test_builder.py:358: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:72: in get_sphinx_output stdout, stderr, app = get_sphinx_app(srcdir, outdir, docname, builder) tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError ____________________________ test_legacy_directive _____________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_legacy_directive0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_legacy_directive0/out')) def test_legacy_directive(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' The Module ========== .. spelling:: teh teh is OK ''') > stdout, stderr, output_text = get_sphinx_output( srcdir, outdir, 'contents', ) tests/test_builder.py:381: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:72: in get_sphinx_output stdout, stderr, app = get_sphinx_app(srcdir, outdir, docname, builder) tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError ____________________________ test_domain_directive _____________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_domain_directive0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_domain_directive0/out')) def test_domain_directive(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' The Module ========== .. spelling:word-list:: teh teh is OK ''') > stdout, stderr, output_text = get_sphinx_output( srcdir, outdir, 'contents', ) tests/test_builder.py:404: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:72: in get_sphinx_output stdout, stderr, app = get_sphinx_app(srcdir, outdir, docname, builder) tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError _______________________________ test_domain_role _______________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_domain_role0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_domain_role0/out')) def test_domain_role(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' The Module ========== :spelling:word:`teh` is OK ''') > stdout, stderr, output_text = get_sphinx_output( srcdir, outdir, 'contents', ) tests/test_builder.py:423: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:72: in get_sphinx_output stdout, stderr, app = get_sphinx_app(srcdir, outdir, docname, builder) tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError _______________________ test_domain_role_multiple_words ________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_domain_role_multiple_word0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_domain_role_multiple_word0/out')) def test_domain_role_multiple_words(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' The Module ========== :spelling:word:`teh is KO` ''') > stdout, stderr, output_text = get_sphinx_output( srcdir, outdir, 'contents', ) tests/test_builder.py:442: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:72: in get_sphinx_output stdout, stderr, app = get_sphinx_app(srcdir, outdir, docname, builder) tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError ______________________________ test_domain_ignore ______________________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_domain_ignore0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_domain_ignore0/out')) def test_domain_ignore(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' The Module ========== :spelling:ignore:`baddddd` is OK ''') > stdout, stderr, output_text = get_sphinx_output( srcdir, outdir, 'contents', ) tests/test_builder.py:487: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:72: in get_sphinx_output stdout, stderr, app = get_sphinx_app(srcdir, outdir, docname, builder) tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError ______________________ test_domain_ignore_multiple_words _______________________ sphinx_project = (local('/tmp/pytest-of-tkloczko/pytest-179/test_domain_ignore_multiple_wo0/src'), local('/tmp/pytest-of-tkloczko/pytest-179/test_domain_ignore_multiple_wo0/out')) def test_domain_ignore_multiple_words(sphinx_project): srcdir, outdir = sphinx_project add_file(srcdir, 'contents.rst', ''' The Module ========== :spelling:ignore:`baddddd` is OK here. But, baddddd is not OK here. Nor, here baddddd. ''') > stdout, stderr, output_text = get_sphinx_output( srcdir, outdir, 'contents', ) tests/test_builder.py:509: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/test_builder.py:72: in get_sphinx_output stdout, stderr, app = get_sphinx_app(srcdir, outdir, docname, builder) tests/test_builder.py:63: in get_sphinx_app app = Sphinx( /usr/lib/python3.8/site-packages/sphinx/application.py:262: in __init__ self._init_builder() /usr/lib/python3.8/site-packages/sphinx/application.py:334: in _init_builder self.builder.init() sphinxcontrib/spelling/builder.py:83: in init self.checker = checker.SpellingChecker( sphinxcontrib/spelling/checker.py:33: in __init__ self.tokenizer = get_tokenizer(tokenizer_lang, filters=filters) /usr/lib/python3.8/site-packages/enchant/tokenize/__init__.py:230: in get_tokenizer tokenizer = f(tokenizer) sphinxcontrib/spelling/filters.py:238: in __init__ contributors = self._get_contributors() sphinxcontrib/spelling/filters.py:247: in _get_contributors p = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) /usr/lib64/python3.8/subprocess.py:493: in run with Popen(*popenargs, **kwargs) as process: /usr/lib64/python3.8/subprocess.py:858: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['git', 'log', '--quiet', '--no-color', '--pretty=format:%(trailers:key=Co-Authored-By,separator=%x0A)%x0A%an%x0A%cn'] executable = b'git', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 12, errread = -1 errwrite = -1, restore_signals = True, start_new_session = False def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, start_new_session): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, os.PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [args] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ('/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh') args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] sys.audit("subprocess.Popen", executable, args, cwd, env) if (_USE_POSIX_SPAWN and os.path.dirname(executable) and preexec_fn is None and not close_fds and not pass_fds and cwd is None and (p2cread == -1 or p2cread > 2) and (c2pwrite == -1 or c2pwrite > 2) and (errwrite == -1 or errwrite > 2) and not start_new_session): self._posix_spawn(args, executable, env, restore_signals, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) return orig_executable = executable # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. errpipe_read, errpipe_write = os.pipe() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: # We must avoid complex work that could involve # malloc or free in the child process to avoid # potential deadlocks, thus we do all this here. # and pass it to fork_exec() if env is not None: env_list = [] for k, v in env.items(): k = os.fsencode(k) if b'=' in k: raise ValueError("illegal environment variable name") env_list.append(k + b'=' + os.fsencode(v)) else: env_list = None # Use execv instead of execve. executable = os.fsencode(executable) if os.path.dirname(executable): executable_list = (executable,) else: # This matches the behavior of os._execvpe(). executable_list = tuple( os.path.join(os.fsencode(dir), executable) for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, start_new_session, preexec_fn) self._child_created = True finally: # be sure the FD is closed no matter what os.close(errpipe_write) self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) # Wait for exec to fail or succeed; possibly raising an # exception (limited in size) errpipe_data = bytearray() while True: part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: break finally: # be sure the FD is closed no matter what os.close(errpipe_read) if errpipe_data: try: pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self._handle_exitstatus(sts) else: self.returncode = sys.maxsize except ChildProcessError: pass try: exception_name, hex_errno, err_msg = ( errpipe_data.split(b':', 2)) # The encoding here should match the encoding # written in by the subprocess implementations # like _posixsubprocess err_msg = err_msg.decode() except ValueError: exception_name = b'SubprocessError' hex_errno = b'0' err_msg = 'Bad exception data from child: {!r}'.format( bytes(errpipe_data)) child_exception_type = getattr( builtins, exception_name.decode('ascii'), SubprocessError) if issubclass(child_exception_type, OSError) and hex_errno: errno_num = int(hex_errno, 16) child_exec_never_called = (err_msg == "noexec") if child_exec_never_called: err_msg = "" # The error must be from chdir(cwd). err_filename = cwd else: err_filename = orig_executable if errno_num != 0: err_msg = os.strerror(errno_num) > raise child_exception_type(errno_num, err_msg, err_filename) E FileNotFoundError: [Errno 2] No such file or directory: 'git' /usr/lib64/python3.8/subprocess.py:1704: FileNotFoundError _______________________________ test_errors_only _______________________________ def test_errors_only(): checker = SpellingChecker(lang='en_US', suggest=False, word_list_filename=None, ) for word, suggestions, line, offset in checker.check('This txt is wrong'): assert not suggestions, 'Suggesting' > assert word == 'txt' E AssertionError: assert 'This' == 'txt' E - txt E + This tests/test_checker.py:19: AssertionError ____________________________ test_with_suggestions _____________________________ def test_with_suggestions(): checker = SpellingChecker(lang='en_US', suggest=True, word_list_filename=None, ) for word, suggestions, line, offset in checker.check('This txt is wrong'): > assert suggestions, 'Not suggesting' E AssertionError: Not suggesting E assert [] tests/test_checker.py:30: AssertionError ______________________________ test_with_wordlist ______________________________ def test_with_wordlist(): checker = SpellingChecker( lang='en_US', suggest=False, word_list_filename=os.path.join(os.path.dirname(__file__), 'test_wordlist.txt') ) words = [w for w, s, l, o in checker.check('This txt is wrong')] > assert not words, 'Did not use personal word list file' E AssertionError: Did not use personal word list file E assert not ['This', 'is', 'wrong'] tests/test_checker.py:43: AssertionError ____________________________ test_with_context_line ____________________________ def test_with_context_line(): checker = SpellingChecker(lang='en_US', suggest=False, word_list_filename=None, context_line=True, ) text = 'Line one\nThis txt is wrong\nLine two' for word, suggestions, line, offset in checker.check(text): assert not suggestions, 'Suggesting' > assert word == 'txt' E AssertionError: assert 'Line' == 'txt' E - txt E + Line tests/test_checker.py:56: AssertionError =============================== warnings summary =============================== tests/test_builder.py::test_setup tests/test_builder.py::test_setup /usr/lib64/python3.8/importlib/__init__.py:127: RemovedInSphinx80Warning: The alias 'sphinx.util.progress_message' is deprecated, use 'sphinx.util.display.progress_message' instead. Check CHANGES for Sphinx API modifications. return _bootstrap._gcd_import(name[level:], package, level) -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html =========================== short test summary info ============================ SKIPPED [1] tests/test_builder.py:257: Not a git repo SKIPPED [27] tests/test_filter.py:49: Not a git repo FAILED tests/test_builder.py::test_setup - FileNotFoundError: [Errno 2] No su... FAILED tests/test_builder.py::test_title - FileNotFoundError: [Errno 2] No su... FAILED tests/test_builder.py::test_body - FileNotFoundError: [Errno 2] No suc... FAILED tests/test_builder.py::test_ignore_literals - FileNotFoundError: [Errn... FAILED tests/test_builder.py::test_several_word_lists - FileNotFoundError: [E... FAILED tests/test_builder.py::test_word_list_default - FileNotFoundError: [Er... FAILED tests/test_builder.py::test_one_word_list_str - FileNotFoundError: [Er... FAILED tests/test_builder.py::test_multiple_word_list_str - FileNotFoundError... FAILED tests/test_builder.py::test_multiple_word_list_list - FileNotFoundErro... FAILED tests/test_builder.py::test_ignore_file - FileNotFoundError: [Errno 2]... FAILED tests/test_builder.py::test_get_suggestions_to_show_all - FileNotFound... FAILED tests/test_builder.py::test_get_suggestions_to_show_limit - FileNotFou... FAILED tests/test_builder.py::test_get_suggestions_to_show_disabled - FileNot... FAILED tests/test_builder.py::test_captions - FileNotFoundError: [Errno 2] No... FAILED tests/test_builder.py::test_legacy_directive - FileNotFoundError: [Err... FAILED tests/test_builder.py::test_domain_directive - FileNotFoundError: [Err... FAILED tests/test_builder.py::test_domain_role - FileNotFoundError: [Errno 2]... FAILED tests/test_builder.py::test_domain_role_multiple_words - FileNotFoundE... FAILED tests/test_builder.py::test_domain_ignore - FileNotFoundError: [Errno ... FAILED tests/test_builder.py::test_domain_ignore_multiple_words - FileNotFoun... FAILED tests/test_checker.py::test_errors_only - AssertionError: assert 'This... FAILED tests/test_checker.py::test_with_suggestions - AssertionError: Not sug... FAILED tests/test_checker.py::test_with_wordlist - AssertionError: Did not us... FAILED tests/test_checker.py::test_with_context_line - AssertionError: assert... ============ 24 failed, 14 passed, 28 skipped, 2 warnings in 3.30s ============= ```
dhellmann commented 1 year ago

@kloczek which git sha did you check out? I can't reproduce this with the sdist tagged 7.7.0.

virtualenv venv
source venv/bin/activate
tar zxf sphinxcontrib-spelling-7.7.0.tar.gz
cd ./sphinxcontrib-spelling-7.7.0
pip install .[test]
pytest -ra -m 'not network'

produces this output from pytest

============================================ test session starts =============================================
platform darwin -- Python 3.10.4, pytest-7.2.1, pluggy-1.0.0
rootdir: /Users/dhellmann/Devel/sphinxcontrib-spelling/isolated-tests/sphinxcontrib-spelling-7.7.0
plugins: cov-4.0.0
collected 66 items

tests/test_builder.py ..........s............                                                          [ 34%]
tests/test_checker.py ......                                                                           [ 43%]
tests/test_filter.py ....sssssssssssssssssssssssssss......                                             [100%]

============================================== warnings summary ==============================================
tests/test_builder.py: 11 warnings
  /Users/dhellmann/Devel/sphinxcontrib-spelling/isolated-tests/sphinxcontrib-spelling-7.7.0/sphinxcontrib/spelling/builder.py:217: PendingDeprecationWarning: nodes.Node.traverse() is obsoleted by Node.findall().
    for node in doctree.traverse(docutils.nodes.Text):

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
========================================== short test summary info ===========================================
SKIPPED [1] tests/test_builder.py:257: Not a git repo
SKIPPED [27] tests/test_filter.py:49: Not a git repo
================================ 38 passed, 28 skipped, 11 warnings in 0.83s =================================

for

$ pytest --version
pytest 7.2.1
kloczek commented 1 year ago

@kloczek which git sha did you check out? I can't reproduce this with the sdist tagged 7.7.0.

virtualenv venv
source venv/bin/activate
tar zxf sphinxcontrib-spelling-7.7.0.tar.gz
cd ./sphinxcontrib-spelling-7.7.0
pip install .[test]
pytest -ra -m 'not network'

You forgot about few steps which I've described opening ticket.

That is how most of the modles are tested in fedora and Debian as well on packaging.

About your question what I'm using as as input resource I'm using autogenerated tat ball from version git tag.

dhellmann commented 1 year ago

Using the archive just created for release 7.7.2, I ran

virtualenv venv
source venv/bin/activate
pip install pytest build setuptools_scm
tar zxf spelling-7.7.2.tar.gz
cd ./spelling-7.7.2
python3 -sBm build -w --no-isolation
pip install dist/sphinxcontrib_spelling-7.7.2-py3-none-any.whl
python -m pytest -ra -m 'not network'

and all of the tests run cleanly

$ python -m pytest -ra -m 'not network'
============================================ test session starts =============================================
platform darwin -- Python 3.10.4, pytest-7.2.1, pluggy-1.0.0
rootdir: /Users/dhellmann/Devel/sphinxcontrib-spelling/isolation-test/spelling-7.7.2
collected 67 items

tests/test_builder.py ..........s.............                                                         [ 35%]
tests/test_checker.py ......                                                                           [ 44%]
tests/test_filter.py ....sssssssssssssssssssssssssss......                                             [100%]

========================================== short test summary info ===========================================
SKIPPED [1] tests/test_builder.py:257: Not a git repo
SKIPPED [27] tests/test_filter.py:49: Not a git repo
======================================= 39 passed, 28 skipped in 0.72s =======================================

The main difference is using python -m pytest instead of just pytest. I believe that's necessary because the tests directory is no longer part of the sdist, and is therefore not installed into the site-packages.

kloczek commented 1 year ago

The main difference is using python -m pytest instead of just pytest. I believe that's necessary because the tests directory is no longer part of the sdist, and is therefore not installed into the site-packages.

pytest should never be used that way and pytest maintainers told about that maaaaany times. Issu is that if it is used pythinn -m foo python interpreter always adds current directry to sys.path. This is why it is provided pytest wrapper script.