Subject: [PATCH] Fix running tests on Python 3.14
From: https://github.com/commonmark/cmark/pull/602
Date: Sun, 1 Mar 2026 22:11:33 +0300

In Python 3.14 multiprocessing module changed start method from fork to forkserver. Now child processes don't have access to parent's memory objects, and pathological_tests.py fails. This change move required objects (mostly object initialization) into child's area.
--- a/test/pathological_tests.py
+++ b/test/pathological_tests.py
@@ -1,29 +1,14 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
-import re
 import argparse
-import sys
-import platform
 import itertools
 import multiprocessing
+import re
+import sys
 import queue
-import time
 from cmark import CMark
 
-TIMEOUT = 5
-
-parser = argparse.ArgumentParser(description='Run cmark tests.')
-parser.add_argument('--program', dest='program', nargs='?', default=None,
-        help='program to test')
-parser.add_argument('--library-dir', dest='library_dir', nargs='?',
-        default=None, help='directory containing dynamic library')
-args = parser.parse_args(sys.argv[1:])
-
-allowed_failures = {"many references": True}
-
-cmark = CMark(prog=args.program, library_dir=args.library_dir)
-
 def hash_collisions():
     REFMAP_SIZE = 16
     COUNT = 25000
@@ -133,13 +118,18 @@ pathological_cmark = {
 
 whitespace_re = re.compile('/s+/')
 
-def run_pathological(q, inp):
+def run_pathological(q, inp, prog, lib_dir):
+    cmark = CMark(prog=prog, library_dir=lib_dir)
     q.put(cmark.to_html(inp))
 
-def run_pathological_cmark(q, inp):
+def run_pathological_cmark(q, inp, prog, lib_dir):
+    cmark = CMark(prog=prog, library_dir=lib_dir)
     q.put(cmark.to_commonmark(inp))
 
-def run_tests():
+def run_tests(args):
+    allowed_failures = {"many references": True}
+    TIMEOUT = 5
+
     q = multiprocessing.Queue()
     passed = []
     errored = []
@@ -150,12 +140,16 @@ def run_tests():
     for description in (*pathological, *pathological_cmark):
         if description in pathological:
             (inp, regex) = pathological[description]
-            p = multiprocessing.Process(target=run_pathological,
-                      args=(q, inp))
+            p = multiprocessing.Process(
+                target=run_pathological,
+                args=(q, inp, args.program, args.library_dir)
+            )
         else:
             (inp, regex) = pathological_cmark[description]
-            p = multiprocessing.Process(target=run_pathological_cmark,
-                      args=(q, inp))
+            p = multiprocessing.Process(
+                target=run_pathological_cmark,
+                args=(q, inp, args.program, args.library_dir)
+            )
         p.start()
         try:
             # wait TIMEOUT seconds or until it finishes
@@ -199,4 +193,10 @@ def run_tests():
         exit(0)
 
 if __name__ == "__main__":
-    run_tests()
+    parser = argparse.ArgumentParser(description='Run cmark tests.')
+    parser.add_argument('--program', dest='program', nargs='?', default=None,
+                    help='program to test')
+    parser.add_argument('--library-dir', dest='library_dir', nargs='?',
+                    default=None, help='directory containing dynamic library')
+    args = parser.parse_args(sys.argv[1:])
+    run_tests(args)
-- 
2.52.0