Skip to content

Commit 5e79487

Browse files
authored
Merge pull request psycopg#744 from dlax/async-to-sync-jobs
feat(tools): possibly run async_to_sync.py concurrently
2 parents 0ed7283 + 5a7f708 commit 5e79487

File tree

1 file changed

+65
-17
lines changed

1 file changed

+65
-17
lines changed

tools/async_to_sync.py

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from __future__ import annotations
1313

1414
import os
15+
from concurrent.futures import ProcessPoolExecutor
1516
import sys
1617
import logging
1718
import subprocess as sp
@@ -59,14 +60,15 @@
5960
SCRIPT_NAME = os.path.basename(sys.argv[0])
6061

6162
logger = logging.getLogger()
62-
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
6363

6464

6565
def main() -> int:
6666
opt = parse_cmdline()
6767
if opt.container:
6868
return run_in_container(opt.container)
6969

70+
logging.basicConfig(level=opt.log_level, format="%(levelname)s %(message)s")
71+
7072
current_ver = ".".join(map(str, sys.version_info[:2]))
7173
if current_ver != PYVER:
7274
logger.warning(
@@ -83,27 +85,50 @@ def main() -> int:
8385
PYVER,
8486
)
8587

86-
outputs = []
87-
for fpin in opt.inputs:
88-
fpout = fpin.parent / fpin.name.replace("_async", "")
89-
outputs.append(str(fpout))
90-
logger.info("converting %s", fpin)
91-
with fpin.open() as f:
92-
source = f.read()
88+
if not opt.convert_all:
89+
inputs, outputs = [], []
90+
for fpin in opt.inputs:
91+
fpout = fpin.parent / fpin.name.replace("_async", "")
92+
if fpout.stat().st_mtime >= fpin.stat().st_mtime:
93+
logger.debug("not converting %s as %s is up to date", fpin, fpout)
94+
continue
95+
inputs.append(fpin)
96+
outputs.append(fpout)
97+
if not outputs:
98+
logger.warning("all output files are up to date, nothing to do")
99+
return 0
100+
101+
else:
102+
inputs = opt.inputs
103+
outputs = [fpin.parent / fpin.name.replace("_async", "") for fpin in inputs]
104+
105+
if opt.jobs == 1:
106+
logger.debug("multi-processing disabled")
107+
for fpin, fpout in zip(inputs, outputs):
108+
convert(fpin, fpout)
109+
else:
110+
with ProcessPoolExecutor(max_workers=opt.jobs) as executor:
111+
executor.map(convert, inputs, outputs)
93112

94-
tree = ast.parse(source, filename=str(fpin))
95-
tree = async_to_sync(tree, filepath=fpin)
96-
output = tree_to_str(tree, fpin)
113+
if opt.check:
114+
return check([str(o) for o in outputs])
97115

98-
with fpout.open("w") as f:
99-
print(output, file=f)
116+
return 0
100117

101-
sp.check_call(["black", "-q", str(fpout)])
102118

103-
if opt.check:
104-
return check(outputs)
119+
def convert(fpin: Path, fpout: Path) -> None:
120+
logger.info("converting %s", fpin)
121+
with fpin.open() as f:
122+
source = f.read()
105123

106-
return 0
124+
tree = ast.parse(source, filename=str(fpin))
125+
tree = async_to_sync(tree, filepath=fpin)
126+
output = tree_to_str(tree, fpin)
127+
128+
with fpout.open("w") as f:
129+
print(output, file=f)
130+
131+
sp.check_call(["black", "-q", str(fpout)])
107132

108133

109134
def check(outputs: list[str]) -> int:
@@ -567,6 +592,29 @@ def parse_cmdline() -> Namespace:
567592
parser.add_argument(
568593
"--all", action="store_true", help="process all the files of the project"
569594
)
595+
parser.add_argument(
596+
"-B",
597+
"--convert-all",
598+
action="store_true",
599+
help="process specified files without checking last modification times",
600+
)
601+
parser.add_argument(
602+
"-j",
603+
"--jobs",
604+
type=int,
605+
metavar="N",
606+
help=(
607+
"process files concurrently using at most N workers; "
608+
"if unspecified, the number of processors on the machine will be used"
609+
),
610+
)
611+
parser.add_argument(
612+
"-L",
613+
"--log-level",
614+
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
615+
default="INFO",
616+
help="Logger level.",
617+
)
570618
container = parser.add_mutually_exclusive_group()
571619
container.add_argument(
572620
"--docker",

0 commit comments

Comments
 (0)