Skip to content

Commit 68c9090

Browse files
authored
Merge pull request winpython#1702 from stonebig/master
simlpify by using logging standard library module
2 parents 76d9b14 + 375604a commit 68c9090

File tree

1 file changed

+75
-96
lines changed

1 file changed

+75
-96
lines changed

winpython/build_winpython.py

Lines changed: 75 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,75 @@
11
# build_winpython.py
22
import os, sys, argparse, datetime, subprocess, shutil
3-
from pathlib import Path
4-
5-
# --- Logging ---
6-
def log_section(logfile, message):
7-
ts = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
8-
section = f"\n{'-'*40}\n({ts}) {message}\n{'-'*40}\n"
9-
print(section)
10-
with open(logfile, 'a', encoding='utf-8') as f:
11-
f.write(section)
3+
import logging
124

5+
from pathlib import Path
6+
from filecmp import cmp
7+
8+
LOG_FORMAT = "%(asctime)s %(levelname)s: %(message)s"
9+
10+
def setup_logging(log_file: Path):
11+
"""Initialize logging to both file and stdout."""
12+
logging.basicConfig(
13+
level=logging.INFO,
14+
format=LOG_FORMAT,
15+
handlers=[
16+
logging.StreamHandler(sys.stdout),
17+
logging.FileHandler(str(log_file), encoding="utf-8", mode='a')
18+
]
19+
)
1320

14-
# --- Utility Functions ---
21+
def log_section(message: str):
22+
logging.info("\n" + "-"*40)
23+
logging.info(message)
24+
logging.info("-"*40)
1525

1626
def delete_folder_if_exists(folder: Path, check_flavor: str = ""):
1727
check_last = folder.parent.name if not folder.is_dir() else folder.name
1828
expected_name = "bu" + check_flavor
19-
2029
if folder.exists() and folder.is_dir() and check_last == expected_name:
21-
print("Removing old backup:", folder)
30+
logging.info(f"Removing old backup: {folder}")
2231
folder_old = folder.with_suffix('.old')
2332
if folder_old.exists():
2433
shutil.rmtree(folder_old)
2534
folder.rename(folder_old)
2635
shutil.rmtree(folder_old)
2736

28-
29-
def run_command(cmd, log_file=None, shell=False, check=True):
30-
print(f"[RUNNING] {' '.join(cmd) if isinstance(cmd, list) else cmd}")
37+
def run_command(cmd, shell=False, check=True):
38+
logging.info(f"[RUNNING] {' '.join(cmd) if isinstance(cmd, list) else cmd}")
3139
with subprocess.Popen(
3240
cmd, shell=shell, stdout=subprocess.PIPE,
3341
stderr=subprocess.STDOUT, universal_newlines=True
3442
) as proc:
35-
with open(log_file, 'a', encoding='utf-8') if log_file else open(os.devnull, 'w') as logf:
36-
for line in proc.stdout:
37-
print(line, end="")
38-
logf.write(line)
43+
for line in proc.stdout:
44+
logging.info(line.rstrip())
3945
if check and proc.wait() != 0:
4046
raise subprocess.CalledProcessError(proc.returncode, cmd)
4147

42-
43-
def pip_install(python_exe: Path, req_file: str, constraints: str, find_links: str, logfile: Path, label: str):
48+
def pip_install(python_exe: Path, req_file: str, constraints: str, find_links: str, label: str):
4449
if req_file and Path(req_file).exists():
4550
cmd = [
4651
str(python_exe), "-m", "pip", "install",
4752
"-r", req_file, "-c", constraints,
4853
"--pre", "--no-index", f"--find-links={find_links}"
4954
]
50-
log_section(logfile, f"Pip-install {label}")
51-
run_command(cmd, log_file=logfile)
55+
log_section(f"Pip-install {label}")
56+
run_command(cmd)
5257
else:
53-
log_section(logfile, f"No {label} specified/skipped")
58+
log_section(f"No {label} specified/skipped")
5459

55-
56-
def patch_winpython(python_exe, logfile):
60+
def patch_winpython(python_exe):
5761
cmd = [
5862
str(python_exe), "-c",
5963
"from wppm import wppm; wppm.Distribution().patch_standard_packages('', to_movable=True)"
6064
]
61-
run_command(cmd, log_file=logfile)
62-
65+
run_command(cmd)
6366

6467
def check_env_bat(winpydirbase: Path):
6568
envbat = winpydirbase / "scripts" / "env.bat"
6669
if not envbat.exists():
6770
raise FileNotFoundError(f"Missing env.bat at {envbat}")
6871

69-
70-
def generate_lockfiles(target_python: Path, winpydirbase: Path, constraints: str, find_links: str, logfile: Path, file_postfix: str):
72+
def generate_lockfiles(target_python: Path, winpydirbase: Path, constraints: str, find_links: str, file_postfix: str):
7173
pip_req = winpydirbase.parent / "requirement_temp.txt"
7274
with subprocess.Popen([str(target_python), "-m", "pip", "freeze"], stdout=subprocess.PIPE) as proc:
7375
packages = [l for l in proc.stdout if b"winpython" not in l]
@@ -76,28 +78,15 @@ def generate_lockfiles(target_python: Path, winpydirbase: Path, constraints: str
7678
for kind in ("", "local"):
7779
out = winpydirbase.parent / f"pylock.{file_postfix}_{kind}.toml"
7880
outreq = winpydirbase.parent / f"requir.{file_postfix}_{kind}.txt"
79-
print(
80-
[str(target_python), "-m", "pip", "lock", "--no-deps", "-c", constraints] +
81-
(["--find-links",find_links] if kind =="local" else []) +
82-
["-r", str(pip_req), "-o", str(out)]
83-
)
84-
subprocess.run(
85-
[str(target_python), "-m", "pip", "lock", "--no-deps", "-c", constraints] +
86-
(["--find-links",find_links] if kind =="local" else []) +
87-
["-r", str(pip_req), "-o", str(out)],
88-
stdout=open(logfile, 'a'), stderr=subprocess.STDOUT, check=True
89-
)
81+
cmd = [str(target_python), "-m", "pip", "lock", "--no-deps", "-c", constraints]
82+
if kind == "local":
83+
cmd += ["--find-links", find_links]
84+
cmd += ["-r", str(pip_req), "-o", str(out)]
85+
run_command(cmd)
9086
# Convert both locks to requirement.txt with hash256
91-
cmd = f"from wppm import wheelhouse as wh; wh.pylock_to_req(r'{out}', r'{outreq}')"
92-
print(
93-
[str(target_python), "-c", cmd]
94-
)
95-
subprocess.run(
96-
[str(target_python), "-c", cmd],
97-
stdout=open(logfile, 'a'), stderr=subprocess.STDOUT, check=False
98-
)
87+
cmd = [str(target_python), "-X", "utf8", "-c", f"from wppm import wheelhouse as wh; wh.pylock_to_req(r'{out}', r'{outreq}')"]
88+
run_command(cmd)
9989
# check equality
100-
from filecmp import cmp
10190
web, local = "", "local"
10291
if not cmp(winpydirbase.parent / f"requir.{file_postfix}_{web}.txt", winpydirbase.parent / f"requir.{file_postfix}_{local}.txt"):
10392
print("ALARM differences in ", winpydirbase.parent / f"requir.{file_postfix}_{web}.txt", winpydirbase.parent / f"requir.{file_postfix}_{local}.txt")
@@ -106,7 +95,7 @@ def generate_lockfiles(target_python: Path, winpydirbase: Path, constraints: str
10695
print ("match ok ",winpydirbase.parent / f"requir.{file_postfix}_{web}.txt", winpydirbase.parent / f"requir.{file_postfix}_{local}.txt")
10796

10897
# --- Main Logic ---
109-
def run_make_py(build_python, winpydirbase, args, logfile):
98+
def run_make_py(build_python, winpydirbase, args):
11099
from . import make
111100
make.make_all(
112101
args.release, args.release_level, basedir_wpy=winpydirbase,
@@ -136,7 +125,7 @@ def main():
136125

137126
# compute paths (same as Step2)...
138127
build_python = Path(args.buildenv) / "python.exe"
139-
winpydirbase = Path(args.winpydirbase) # from Step2 logic
128+
winpydirbase = Path(args.winpydirbase)
140129
target_python = winpydirbase / "python" / "python.exe"
141130

142131
# Setup paths and logs
@@ -145,117 +134,107 @@ def main():
145134
log_dir.mkdir(exist_ok=True)
146135
time_str = now.strftime("%Y-%m-%d_at_%H%M")
147136
log_file = log_dir / f"build_{args.python_target}_{args.flavor}_{args.release_level}_{time_str}.txt"
148-
149-
#logs termination
137+
setup_logging(log_file)
138+
139+
# Logs termination and version naming
150140
z = Path(winpydirbase).name[(4+len(args.arch)):-len(args.release_level)]
151141
tada = f"{z[:1]}_{z[1:3]}_{z[3]}_{args.release}"
152142
winpyver2 = tada.replace('_', '.')
153143
file_postfix = f"{args.arch}-{tada}{args.flavor}{args.release_level}"
154144

155-
log_section(log_file, f"Preparing build for Python {args.python_target} ({args.arch}-bit)")
156-
157-
log_section(log_file, f"🙏 Step 0: displace old {Path(winpydirbase)}")
145+
log_section(f"Preparing build for Python {args.python_target} ({args.arch}-bit)")
158146

147+
log_section(f"🙏 Step 0: displace old {Path(winpydirbase)}")
159148
delete_folder_if_exists(winpydirbase.parent, check_flavor=args.flavor) #bu{flavor]}
160149

161-
log_section(log_file, f"🙏 Step 1: make.py Python with {str(build_python)} at ({winpydirbase}")
162-
run_make_py(str(build_python), winpydirbase, args, log_file)
150+
log_section(f"🙏 Step 1: make.py Python with {str(build_python)} at ({winpydirbase}")
151+
run_make_py(str(build_python), winpydirbase, args)
163152

164153
check_env_bat(winpydirbase)
165154

166-
log_section(log_file, "🙏 Step 3: install requirements")
155+
log_section("🙏 Step 3: install requirements")
167156

168157
for label, req in [
169158
("Mandatory", args.mandatory_req),
170159
("Pre", args.pre_req),
171160
("Main", args.requirements),
172161
]:
173-
pip_install(target_python, req, args.constraints, args.find_links, log_file, label)
162+
pip_install(target_python, req, args.constraints, args.find_links, label)
174163

175-
log_section(log_file, "🙏 Step 4: Patch Winpython")
176-
patch_winpython(target_python, log_file)
164+
log_section("🙏 Step 4: Patch Winpython")
165+
patch_winpython(target_python)
177166

178167
if args.wheelhousereq:
179-
log_section(log_file, f"🙏 Step 5: install wheelhouse requirements {args.wheelhousereq}")
168+
log_section(f"🙏 Step 5: install wheelhouse requirements {args.wheelhousereq}")
180169
wheelhousereq = Path(args.wheelhousereq)
181170
kind = "local"
182171
out = winpydirbase.parent / f"pylock.{file_postfix}_wheels{kind}.toml"
183172
outreq = winpydirbase.parent / f"requir.{file_postfix}_wheels{kind}.txt"
184173
if wheelhousereq.is_file():
185174
# Generate pylock from wheelhousereq
186175
cmd = [str(target_python), "-m" , "pip", "lock","--no-index", "--trusted-host=None",
187-
"--find-links", args.find_links, "-c", args.constraints, "-r", wheelhousereq,
188-
"-o", out ]
189-
subprocess.run(cmd, stdout=open(log_file, 'a'), stderr=subprocess.STDOUT, check=True)
176+
"--find-links", args.find_links, "-c", str(args.constraints), "-r", str(wheelhousereq),
177+
"-o", str(out) ]
178+
run_command(cmd)
190179
# Convert pylock to requirements with hash
191-
cmd = f"from wppm import wheelhouse as wh; wh.pylock_to_req(r'{out}', r'{outreq}')"
192-
print( [str(target_python), "-c", cmd] )
193-
subprocess.run([str(target_python), "-c", cmd],
194-
stdout=open(log_file, 'a'), stderr=subprocess.STDOUT, check=False
195-
)
180+
cmd = [str(target_python), "-X", "utf8", "-c", f"from wppm import wheelhouse as wh; wh.pylock_to_req(r'{out}', r'{outreq}')"]
181+
run_command(cmd, check=False)
196182

197183
kind = ""
198184
outw = winpydirbase.parent / f"pylock.{file_postfix}_wheels{kind}.toml"
199185
outreqw = winpydirbase.parent / f"requir.{file_postfix}_wheels{kind}.txt"
200186
# Generate web pylock from local frozen hashes
201187
cmd = [str(target_python), "-m" , "pip", "lock","--no-deps", "--require-hashes",
202188
"-r", str(outreq), "-o", str(outw) ]
203-
subprocess.run(cmd, stdout=open(log_file, 'a'), stderr=subprocess.STDOUT, check=True)
204-
cmd = f"from wppm import wheelhouse as wh; wh.pylock_to_req(r'{outw}', r'{outreqw}')"
205-
print( [str(target_python), "-c", cmd] )
206-
subprocess.run([str(target_python), "-c", cmd],
207-
stdout=open(log_file, 'a'), stderr=subprocess.STDOUT, check=False
208-
)
189+
run_command(cmd)
190+
cmd = [str(target_python), "-X", "utf8", "-c", f"from wppm import wheelhouse as wh; wh.pylock_to_req(r'{outw}', r'{outreqw}')"]
191+
run_command(cmd, check=False)
209192

210193
# Use wppm to download local from req made with web hashes
211194
wheelhouse = winpydirbase / "wheelhouse" / "included.wheels"
212195
cmd = [str(target_python), "-X", "utf8", "-m", "wppm", str(out), "-ws", args.find_links,
213196
"-wd", str(wheelhouse)
214197
]
215-
print(cmd)
216-
subprocess.run(cmd, stdout=open(log_file, 'a'), stderr=subprocess.STDOUT, check=False)
217-
198+
run_command(cmd, check=False)
218199

219-
log_section(log_file, "🙏 Step 6: install lockfiles")
220-
print(target_python, winpydirbase, args.constraints, args.find_links, log_file)
221-
generate_lockfiles(target_python, winpydirbase, args.constraints, args.find_links, log_file, file_postfix)
200+
log_section("🙏 Step 6: install lockfiles")
201+
print(target_python, winpydirbase, args.constraints, args.find_links, file_postfix)
202+
generate_lockfiles(target_python, winpydirbase, args.constraints, args.find_links, file_postfix)
222203

223204
# 6) generate changelog
224205
mdn = f"WinPython{args.flavor}-{args.arch}bit-{winpyver2}.md"
225206
out = f"WinPython{args.flavor}-{args.arch}bit-{winpyver2}_History.md"
226207
changelog_dir = log_dir.parent/ "changelogs"
227208

228-
log_section(log_file, f"🙏 Step 6: generate changelog {mdn}")
209+
log_section(f"🙏 Step 6: generate changelog {mdn}")
229210

230211
cmd = ["set", f"WINPYVER2={winpyver2}&", "set", f"WINPYFLAVOR={args.flavor}&",
231212
"set", f"WINPYVER={winpyver2}{args.flavor}{args.release_level}&",
232-
str(target_python), "-c" ,
213+
str(target_python), "-X", "utf8", "-c" ,
233214
(
234215
"from wppm import wppm;"
235216
"result = wppm.Distribution().generate_package_index_markdown();"
236217
f"open(r'{winpydirbase.parent / mdn}', 'w', encoding='utf-8').write(result)"
237218
)]
238-
print(cmd)
239-
subprocess.run(cmd, stdout=open(log_file, 'a'), stderr=subprocess.STDOUT, check=True, shell=True)
219+
run_command(cmd, shell=True)
240220
shutil.copyfile (winpydirbase.parent / mdn, changelog_dir / mdn)
241221

242-
cmd = [str(target_python), "-c",
222+
cmd = [str(target_python), "-X", "utf8", "-c",
243223
(
244224
"from wppm import diff;"
245225
f"result = diff.compare_package_indexes('{winpyver2}', searchdir=r'{changelog_dir}', flavor=r'{args.flavor}', architecture={args.arch});"
246226
f"open(r'{winpydirbase.parent / out}', 'w', encoding='utf-8').write(result)"
247227
)]
248-
subprocess.run(cmd, stdout=open(log_file, 'a'), stderr=subprocess.STDOUT, check=True)
228+
run_command(cmd, check=False)
249229
shutil.copyfile (winpydirbase.parent / out, changelog_dir / out)
250-
log_section(log_file, "✅ Step 6 complete")
230+
log_section("✅ Step 6 complete")
251231

252232
if args.create_installer != "":
253-
log_section(log_file, "🙏 Step 7 Create Installer")
233+
log_section("🙏 Step 7 Create Installer")
254234
stem = f"WinPython{args.arch}-{winpyver2}{args.flavor}{args.release_level}"
255-
cmd = f"from wppm import utils; utils.command_installer_7zip(r'{winpydirbase}', r'{winpydirbase.parent}', r'{stem}', r'{args.create_installer}')"
256-
print( [str(target_python), "-c", cmd] )
257-
subprocess.run([str(target_python), "-c", cmd],
258-
stdout=open(log_file, 'a'), stderr=subprocess.STDOUT, check=False)
235+
cmd = [str(target_python), "-c",
236+
f"from wppm import utils; utils.command_installer_7zip(r'{winpydirbase}', r'{winpydirbase.parent}', r'{stem}', r'{args.create_installer}')" ]
237+
run_command(cmd, check=False)
259238

260239
if __name__ == '__main__':
261240
main()

0 commit comments

Comments
 (0)