From 3f265e48eb11bf53b42c7913834206b1b26c31d3 Mon Sep 17 00:00:00 2001 From: A5rocks Date: Sat, 31 Aug 2024 16:21:43 +0900 Subject: [PATCH 1/7] Update open_process types --- newsfragments/3076.bugfix.rst | 1 + src/trio/_subprocess.py | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 14 deletions(-) create mode 100644 newsfragments/3076.bugfix.rst diff --git a/newsfragments/3076.bugfix.rst b/newsfragments/3076.bugfix.rst new file mode 100644 index 0000000000..48aa54127a --- /dev/null +++ b/newsfragments/3076.bugfix.rst @@ -0,0 +1 @@ +Update ``trio.lowlevel.open_process``'s documentation to allow bytes. diff --git a/src/trio/_subprocess.py b/src/trio/_subprocess.py index 90ab9cc16a..306092123c 100644 --- a/src/trio/_subprocess.py +++ b/src/trio/_subprocess.py @@ -304,7 +304,7 @@ def kill(self) -> None: async def _open_process( - command: list[str] | str, + command: StrOrBytesPath | Sequence[StrOrBytesPath], *, stdin: int | HasFileno | None = None, stdout: int | HasFileno | None = None, @@ -329,13 +329,13 @@ async def _open_process( want. Args: - command (list or str): The command to run. Typically this is a - sequence of strings such as ``['ls', '-l', 'directory with spaces']``, - where the first element names the executable to invoke and the other - elements specify its arguments. With ``shell=True`` in the - ``**options``, or on Windows, ``command`` may alternatively - be a string, which will be parsed following platform-dependent - :ref:`quoting rules `. + command (str or byte or sequence of either): The command to run. Typically + this is a sequence of strings or bytes such as ``['ls', '-l', + 'directory with spaces']``, where the first element names the + executable to invoke and the other elements specify its arguments. + With ``shell=True`` in the ``**options``, or on Windows, ``command`` + may alternatively be a string or bytes, which will be parsed following + platform-dependent :ref:`quoting rules `. stdin: Specifies what the child process's standard input stream should connect to: output written by the parent (``subprocess.PIPE``), nothing (``subprocess.DEVNULL``), @@ -369,15 +369,15 @@ async def _open_process( ) if os.name == "posix": - if isinstance(command, str) and not options.get("shell"): + if isinstance(command, (str, bytes)) and not options.get("shell"): raise TypeError( - "command must be a sequence (not a string) if shell=False " - "on UNIX systems", + "command must be a sequence (not a string or bytes) if " + "shell=False on UNIX systems", ) - if not isinstance(command, str) and options.get("shell"): + if not isinstance(command, (str, bytes)) and options.get("shell"): raise TypeError( - "command must be a string (not a sequence) if shell=True " - "on UNIX systems", + "command must be a string or bytes (not a sequence) if " + "shell=True on UNIX systems", ) trio_stdin: ClosableSendStream | None = None From 9f38190a75ba07f687c00f5cced927f85526865d Mon Sep 17 00:00:00 2001 From: A5rocks Date: Sat, 31 Aug 2024 16:21:57 +0900 Subject: [PATCH 2/7] Make `gen_exports` not use carriage returns on Windows --- src/trio/_tools/gen_exports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/trio/_tools/gen_exports.py b/src/trio/_tools/gen_exports.py index 524a65f90d..91969d6bfe 100755 --- a/src/trio/_tools/gen_exports.py +++ b/src/trio/_tools/gen_exports.py @@ -303,7 +303,7 @@ def process(files: Iterable[File], *, do_test: bool) -> None: print("Generated sources are up to date.") else: for new_path, new_source in new_files.items(): - with open(new_path, "w", encoding="utf-8") as f: + with open(new_path, "w", encoding="utf-8", newline="\n") as f: f.write(new_source) print("Regenerated sources successfully.") if not matches_disk: From 9d9216e1dbcc8e134d0869f5e43b08dde1c9f910 Mon Sep 17 00:00:00 2001 From: A5rocks Date: Sat, 31 Aug 2024 16:25:36 +0900 Subject: [PATCH 3/7] Reference types correctly for the argument --- src/trio/_subprocess.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/trio/_subprocess.py b/src/trio/_subprocess.py index 306092123c..628c5dfc97 100644 --- a/src/trio/_subprocess.py +++ b/src/trio/_subprocess.py @@ -329,9 +329,9 @@ async def _open_process( want. Args: - command (str or byte or sequence of either): The command to run. Typically - this is a sequence of strings or bytes such as ``['ls', '-l', - 'directory with spaces']``, where the first element names the + command (str or bytes or Sequence[str] or Sequence[bytes]): The command to + run. Typically this is a sequence of strings or bytes such as ``['ls', + '-l', 'directory with spaces']``, where the first element names the executable to invoke and the other elements specify its arguments. With ``shell=True`` in the ``**options``, or on Windows, ``command`` may alternatively be a string or bytes, which will be parsed following From c0b210565218b2f432674564d3164523c750360a Mon Sep 17 00:00:00 2001 From: EXPLOSION Date: Sun, 1 Sep 2024 10:04:09 +0900 Subject: [PATCH 4/7] Remove unnecessary argument type in docstring --- src/trio/_subprocess.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/trio/_subprocess.py b/src/trio/_subprocess.py index 628c5dfc97..a6f1ee738a 100644 --- a/src/trio/_subprocess.py +++ b/src/trio/_subprocess.py @@ -329,13 +329,13 @@ async def _open_process( want. Args: - command (str or bytes or Sequence[str] or Sequence[bytes]): The command to - run. Typically this is a sequence of strings or bytes such as ``['ls', - '-l', 'directory with spaces']``, where the first element names the - executable to invoke and the other elements specify its arguments. - With ``shell=True`` in the ``**options``, or on Windows, ``command`` - may alternatively be a string or bytes, which will be parsed following - platform-dependent :ref:`quoting rules `. + command: The command to run. Typically this is a sequence of strings or + bytes such as ``['ls', '-l', 'directory with spaces']``, where the + first element names the executable to invoke and the other elements + specify its arguments. With ``shell=True`` in the ``**options``, or on + Windows, ``command`` may alternatively be a string or bytes, which + will be parsed following platform-dependent :ref:`quoting rules + `. stdin: Specifies what the child process's standard input stream should connect to: output written by the parent (``subprocess.PIPE``), nothing (``subprocess.DEVNULL``), From ede658f464adbe3ee4904fd41adb137071856450 Mon Sep 17 00:00:00 2001 From: A5rocks Date: Sun, 1 Sep 2024 10:48:38 +0900 Subject: [PATCH 5/7] Disable caching to make CI pass --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 074943ec63..0c3cf098d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,8 +64,10 @@ jobs: # 'PyPy' -> 'pypy-3.9' python-version: ${{ fromJSON(format('["{0}", "{1}"]', format('{0}.0-alpha - {0}.X', matrix.python), matrix.python))[startsWith(matrix.python, 'pypy')] }} architecture: '${{ matrix.arch }}' - cache: pip - cache-dependency-path: test-requirements.txt + # Caching can lead to issues with constraints on PyPy as in #3076. + # This is probably a bug in the cache key, but I'm not sure. + # cache: pip + # cache-dependency-path: test-requirements.txt - name: Run tests run: ./ci.sh shell: bash From da9d9204e0c39a4adabf17f35be1046b4390ffeb Mon Sep 17 00:00:00 2001 From: EXPLOSION Date: Tue, 3 Sep 2024 09:31:56 +0900 Subject: [PATCH 6/7] Cache issues were transient? --- .github/workflows/ci.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c3cf098d3..074943ec63 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,10 +64,8 @@ jobs: # 'PyPy' -> 'pypy-3.9' python-version: ${{ fromJSON(format('["{0}", "{1}"]', format('{0}.0-alpha - {0}.X', matrix.python), matrix.python))[startsWith(matrix.python, 'pypy')] }} architecture: '${{ matrix.arch }}' - # Caching can lead to issues with constraints on PyPy as in #3076. - # This is probably a bug in the cache key, but I'm not sure. - # cache: pip - # cache-dependency-path: test-requirements.txt + cache: pip + cache-dependency-path: test-requirements.txt - name: Run tests run: ./ci.sh shell: bash From 1688da0f2748a3f0957a6520a2eb31b8a7ee4c49 Mon Sep 17 00:00:00 2001 From: EXPLOSION Date: Wed, 4 Sep 2024 07:12:33 +0900 Subject: [PATCH 7/7] Document paths in the docstring --- src/trio/_subprocess.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/trio/_subprocess.py b/src/trio/_subprocess.py index a6f1ee738a..263225ffca 100644 --- a/src/trio/_subprocess.py +++ b/src/trio/_subprocess.py @@ -333,9 +333,10 @@ async def _open_process( bytes such as ``['ls', '-l', 'directory with spaces']``, where the first element names the executable to invoke and the other elements specify its arguments. With ``shell=True`` in the ``**options``, or on - Windows, ``command`` may alternatively be a string or bytes, which - will be parsed following platform-dependent :ref:`quoting rules - `. + Windows, ``command`` can be a string or bytes, which will be parsed + following platform-dependent :ref:`quoting rules + `. In all cases ``command`` can be a path or a + sequence of paths. stdin: Specifies what the child process's standard input stream should connect to: output written by the parent (``subprocess.PIPE``), nothing (``subprocess.DEVNULL``), @@ -369,6 +370,7 @@ async def _open_process( ) if os.name == "posix": + # TODO: how do paths and sequences thereof play with `shell=True`? if isinstance(command, (str, bytes)) and not options.get("shell"): raise TypeError( "command must be a sequence (not a string or bytes) if "