Skip to content

Commit

Permalink
Enable support for free-threading
Browse files Browse the repository at this point in the history
This PR:
1. marks the `libcst.native` module as free-threading-compatible
2. replaces the use of ProcessPoolExecutor with ThreadPoolExecutor if free-threaded CPython is detected at runtime

This depends on #1294 and #1289.
  • Loading branch information
zsol committed Feb 22, 2025
1 parent 00ab3af commit 905a843
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 9 deletions.
17 changes: 12 additions & 5 deletions libcst/codemod/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@
import difflib
import os.path
import re
import functools
import subprocess
import sys
import time
import traceback
from concurrent.futures import as_completed, Executor, ProcessPoolExecutor
from concurrent.futures import as_completed, Executor
from copy import deepcopy
from dataclasses import dataclass, replace
from multiprocessing import cpu_count
from pathlib import Path
from typing import Any, AnyStr, cast, Dict, List, Optional, Sequence, Union
from typing import Any, AnyStr, cast, Dict, List, Optional, Sequence, Union, Callable

from libcst import parse_module, PartialParserConfig
from libcst.codemod._codemod import Codemod
Expand Down Expand Up @@ -608,14 +609,20 @@ def parallel_exec_transform_with_prettyprint( # noqa: C901
python_version=python_version,
)

pool_impl: type[Executor]
pool_impl: Callable[[], Executor]
if total == 1 or jobs == 1:
# Simple case, we should not pay for process overhead.
# Let's just use a dummy synchronous executor.
jobs = 1
pool_impl = DummyExecutor
elif getattr(sys, "_is_gil_enabled", lambda: False)():
from concurrent.futures import ThreadPoolExecutor

pool_impl = functools.partial(ThreadPoolExecutor, max_workers=jobs)
else:
pool_impl = ProcessPoolExecutor
from concurrent.futures import ProcessPoolExecutor

pool_impl = functools.partial(ProcessPoolExecutor, max_workers=jobs)
# Warm the parser, pre-fork.
parse_module(
"",
Expand All @@ -631,7 +638,7 @@ def parallel_exec_transform_with_prettyprint( # noqa: C901
warnings: int = 0
skips: int = 0

with pool_impl(max_workers=jobs) as executor: # type: ignore
with pool_impl() as executor: # type: ignore
args = [
{
"transformer": transform,
Expand Down
3 changes: 0 additions & 3 deletions libcst/codemod/_dummy_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ class DummyExecutor(Executor):
Synchronous dummy `concurrent.futures.Executor` analogue.
"""

def __init__(self, max_workers: Optional[int] = None) -> None:
pass

def submit(
self,
# pyre-ignore
Expand Down
2 changes: 1 addition & 1 deletion native/libcst/src/py.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use crate::nodes::traits::py::TryIntoPy;
use pyo3::prelude::*;

#[pymodule]
#[pymodule(gil_used = false)]
#[pyo3(name = "native")]
pub fn libcst_native(_py: Python, m: &Bound<PyModule>) -> PyResult<()> {
#[pyfn(m)]
Expand Down

0 comments on commit 905a843

Please sign in to comment.