Skip to content

Commit b8133c2

Browse files
zsolngoldbaum
authored andcommitted
Enable support for free-threading
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 Instagram#1294 and Instagram#1289.
1 parent 10565da commit b8133c2

File tree

3 files changed

+13
-9
lines changed

3 files changed

+13
-9
lines changed

libcst/codemod/_cli.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,17 @@
1010
import difflib
1111
import os.path
1212
import re
13+
import functools
1314
import subprocess
1415
import sys
1516
import time
1617
import traceback
17-
from concurrent.futures import as_completed, Executor, ProcessPoolExecutor
18+
from concurrent.futures import as_completed, Executor
1819
from copy import deepcopy
1920
from dataclasses import dataclass, replace
2021
from multiprocessing import cpu_count
2122
from pathlib import Path
22-
from typing import Any, AnyStr, cast, Dict, List, Optional, Sequence, Union
23+
from typing import Any, AnyStr, cast, Dict, List, Optional, Sequence, Union, Callable
2324

2425
from libcst import parse_module, PartialParserConfig
2526
from libcst.codemod._codemod import Codemod
@@ -608,14 +609,20 @@ def parallel_exec_transform_with_prettyprint( # noqa: C901
608609
python_version=python_version,
609610
)
610611

611-
pool_impl: type[Executor]
612+
pool_impl: Callable[[], Executor]
612613
if total == 1 or jobs == 1:
613614
# Simple case, we should not pay for process overhead.
614615
# Let's just use a dummy synchronous executor.
615616
jobs = 1
616617
pool_impl = DummyExecutor
618+
elif getattr(sys, "_is_gil_enabled", lambda: False)():
619+
from concurrent.futures import ThreadPoolExecutor
620+
621+
pool_impl = functools.partial(ThreadPoolExecutor, max_workers=jobs)
617622
else:
618-
pool_impl = ProcessPoolExecutor
623+
from concurrent.futures import ProcessPoolExecutor
624+
625+
pool_impl = functools.partial(ProcessPoolExecutor, max_workers=jobs)
619626
# Warm the parser, pre-fork.
620627
parse_module(
621628
"",
@@ -631,7 +638,7 @@ def parallel_exec_transform_with_prettyprint( # noqa: C901
631638
warnings: int = 0
632639
skips: int = 0
633640

634-
with pool_impl(max_workers=jobs) as executor: # type: ignore
641+
with pool_impl() as executor: # type: ignore
635642
args = [
636643
{
637644
"transformer": transform,

libcst/codemod/_dummy_pool.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ class DummyExecutor(Executor):
2222
Synchronous dummy `concurrent.futures.Executor` analogue.
2323
"""
2424

25-
def __init__(self, max_workers: Optional[int] = None) -> None:
26-
pass
27-
2825
def submit(
2926
self,
3027
# pyre-ignore

native/libcst/src/py.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use crate::nodes::traits::py::TryIntoPy;
77
use pyo3::prelude::*;
88

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

0 commit comments

Comments
 (0)