From 280aef336bbcf77ad2cd9ecf41b9e3b1a228d742 Mon Sep 17 00:00:00 2001 From: Julian Smith Date: Fri, 20 Mar 2026 10:13:09 +0000 Subject: [PATCH 1/3] changes.txt: added date of 1.27.2.2 release. --- changes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changes.txt b/changes.txt index 804544e79..29cb7adeb 100644 --- a/changes.txt +++ b/changes.txt @@ -2,7 +2,7 @@ Change Log ========== -**Changes in version 1.27.2.2** +**Changes in version 1.27.2.2** (2026-03-20) * Fixed issues: From 389d8075b8ae83f0ca05dbdc7504385cf2391b53 Mon Sep 17 00:00:00 2001 From: Julian Smith Date: Mon, 23 Mar 2026 12:38:59 +0000 Subject: [PATCH 2/3] docs/faq/index.rst: new item: Can I use multithreading with PyMuPDF, perhaps with free-threading Python? --- docs/faq/index.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/faq/index.rst b/docs/faq/index.rst index 812ec9ed7..c36362f72 100644 --- a/docs/faq/index.rst +++ b/docs/faq/index.rst @@ -1133,6 +1133,24 @@ FAQ
Note: Threading with GIL release was tested but found to have intolerable overhead. Multiprocessing is the better approach for parallelism.
+ +
+
QCan I use multithreading with PyMuPDF, perhaps with free-threading Python?+
+
+

No, PyMuPDF does not support multithreaded use, + even with newer free-thread Python. + +

Making PyMuPDF work with threads is a tricky problem. + The underlying MuPDF library only provides partial thread safety so the results would not be as performant as might be naively assumed, + and the implementation would inevitably introduce and expose subtle bugs. + +

Any thread-safe implementation of PyMuPDF would also necessarily impose a single-threaded overhead. + +

The preferred approach is to use multiple processes instead of multiple threads. + This gives most of what is generally required, + with simplicity and guaranteed correctness. +

+
From 01772447de935e250bb97f918dc880ba42b0f4ee Mon Sep 17 00:00:00 2001 From: Julian Smith Date: Mon, 23 Mar 2026 14:34:45 +0000 Subject: [PATCH 3/3] tests/test_codespell.py: reduce length of codespell command line. We use codespell's new @FILE arg. --- tests/test_codespell.py | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/tests/test_codespell.py b/tests/test_codespell.py index 9b837ea37..cac5fe09a 100644 --- a/tests/test_codespell.py +++ b/tests/test_codespell.py @@ -49,20 +49,28 @@ def test_codespell(): import pipcl finally: del sys.path[0] + git_files = pipcl.git_items(root) - for p in git_files: - _, ext = os.path.splitext(p) - if ext in ('.png', '.pdf', '.jpg', '.svg'): - pass - else: - command += f' {p}\n' + command_args_path = os.path.normpath(f'{__file__}/../test_codespell_args.txt') + command += f' @{command_args_path}' + + with open(command_args_path, 'w') as f: + + for p in git_files: + _, ext = os.path.splitext(p) + if ext in ('.png', '.pdf', '.jpg', '.svg'): + pass + else: + #command += f' {p}\n' + print(p, file=f) if platform.system() != 'Windows': command = command.replace('\n', ' \\\n') - # Don't print entire command because very long, and will be displayed - # anyway if there is an error. - #print(f'test_codespell(): Running: {command}') - print(f'Running codespell.') + if 0: + with open(command_args_path) as f: + command_args_path_contents = f.read() + print(f'command_args_path:{command_args_path_contents}') + print(f'Running codespell: {command}') subprocess.run(command, shell=1, check=1) print('test_codespell(): codespell succeeded.')