Skip to content

Commit e3abe73

Browse files
committed
chore: satisfy linting concerns from ruff
- a step toward resolving #138 There may be some opinionated changes about the requirement to explicitly use `check=<bool>` for `subprocess.run()` calls.
1 parent da13980 commit e3abe73

5 files changed

Lines changed: 149 additions & 103 deletions

File tree

circuitpython_build_tools/build.py

Lines changed: 119 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,20 @@
1010
import multiprocessing
1111
import os
1212
import os.path
13-
import platform
1413
import pathlib
14+
import platform
1515
import re
16-
import requests
17-
import semver
1816
import shutil
1917
import stat
20-
import sys
2118
import subprocess
19+
import sys
2220
import tempfile
21+
from fileinput import filename
22+
from typing import Optional
23+
2324
import platformdirs
25+
import requests
26+
import semver
2427

2528

2629
@functools.cache
@@ -89,15 +92,19 @@ def version_string(path=None, *, valid_semver=False):
8992
tag = subprocess.run(
9093
"git describe --tags --exact-match",
9194
shell=True,
92-
stdout=subprocess.PIPE,
93-
stderr=subprocess.PIPE,
95+
capture_output=True,
9496
cwd=path,
97+
check=False, # error handled below
9598
)
9699
if tag.returncode == 0:
97100
version = tag.stdout.strip().decode("utf-8", "strict")
98101
else:
99102
describe = subprocess.run(
100-
"git describe --tags --always", shell=True, stdout=subprocess.PIPE, cwd=path
103+
"git describe --tags --always",
104+
shell=True,
105+
stdout=subprocess.PIPE,
106+
cwd=path,
107+
check=True, # Let exception propagate an error from git
101108
)
102109
describe = describe.stdout.strip().decode("utf-8", "strict").rsplit("-", maxsplit=2)
103110
if len(describe) == 3:
@@ -106,7 +113,11 @@ def version_string(path=None, *, valid_semver=False):
106113
else:
107114
tag = "0.0.0"
108115
commit_count = subprocess.run(
109-
"git rev-list --count HEAD", shell=True, stdout=subprocess.PIPE, cwd=path
116+
"git rev-list --count HEAD",
117+
shell=True,
118+
stdout=subprocess.PIPE,
119+
cwd=path,
120+
check=True, # Let exception propagate an error from git
110121
)
111122
additional_commits = commit_count.stdout.strip().decode("utf-8", "strict")
112123
commitish = describe[0]
@@ -135,17 +146,21 @@ def mpy_cross(version, quiet=False):
135146
# Try to pull from S3
136147
uname = platform.uname()
137148
s3_url = None
138-
if uname[0].title() == "Linux" and uname[4].lower() in ("amd64", "x86_64"):
149+
if uname[0].title() == "Linux" and uname[4].lower() in {"amd64", "x86_64"}:
139150
s3_url = f"{S3_MPY_PREFIX}/linux-amd64/mpy-cross-linux-amd64-{circuitpython_tag}.static"
140151
elif uname[0].title() == "Linux" and uname[4].lower() == "armv7l":
141-
s3_url = f"{S3_MPY_PREFIX}/linux-raspbian/mpy-cross-linux-raspbian-{circuitpython_tag}.static-raspbian"
152+
s3_url = (
153+
f"{S3_MPY_PREFIX}/linux-raspbian/mpy-cross-linux-raspbian-{circuitpython_tag}."
154+
"static-raspbian"
155+
)
142156
elif uname[0].title() == "Darwin":
143157
s3_url = f"{S3_MPY_PREFIX}/macos/mpy-cross-macos-{circuitpython_tag}-universal"
144-
elif uname[0].title() == "Windows" and uname[4].lower() in ("amd64", "x86_64"):
158+
elif uname[0].title() == "Windows" and uname[4].lower() in {"amd64", "x86_64"}:
145159
s3_url = f"{S3_MPY_PREFIX}/windows/mpy-cross-windows-{circuitpython_tag}.static.exe"
146160
elif not quiet:
147161
print(
148-
f"Pre-built mpy-cross not available for sysname='{uname[0]}' release='{uname[2]}' machine='{uname[4]}'."
162+
"Pre-built mpy-cross not available for",
163+
f"sysname='{uname[0]}' release='{uname[2]}' machine='{uname[4]}'.",
149164
)
150165

151166
if s3_url is not None:
@@ -201,13 +216,13 @@ def mpy_cross(version, quiet=False):
201216

202217

203218
def _munge_to_temp(original_path, temp_file, library_version):
204-
with open(original_path, "r", encoding="utf-8") as original_file:
219+
with open(original_path, encoding="utf-8") as original_file:
205220
for line in original_file:
206-
line = line.strip("\n")
207-
if line.startswith("__version__"):
208-
line = line.replace("0.0.0-auto.0", library_version)
209-
line = line.replace("0.0.0+auto.0", library_version)
210-
print(line, file=temp_file)
221+
ln = line.strip("\n")
222+
if ln.startswith("__version__"):
223+
ln = ln.replace("0.0.0-auto.0", library_version)
224+
ln = ln.replace("0.0.0+auto.0", library_version)
225+
print(ln, file=temp_file)
211226
temp_file.flush()
212227

213228

@@ -230,7 +245,8 @@ def get_package_info(library_path, package_folder_prefix):
230245

231246
if blocklisted:
232247
print(
233-
f"{lib_path}/settings.toml:1: {blocklisted[0]} blocklisted: not using metadata from pyproject.toml"
248+
f"{lib_path}/settings.toml:1: {blocklisted[0]}",
249+
"blocklisted: not using metadata from pyproject.toml",
234250
)
235251
py_modules = packages = ()
236252

@@ -241,7 +257,7 @@ def get_package_info(library_path, package_folder_prefix):
241257
if packages and py_modules:
242258
raise ValueError("Cannot specify both tool.setuptools.py-modules and .packages")
243259

244-
elif packages:
260+
if packages:
245261
if len(packages) > 1:
246262
raise ValueError("Only a single package is supported")
247263
package_name = packages[0]
@@ -264,28 +280,16 @@ def get_package_info(library_path, package_folder_prefix):
264280

265281
else:
266282
print(f"{lib_path}: Using legacy autodetection")
267-
package_info["is_package"] = False
268-
for file in glob_search:
269-
if file.parts[parent_idx] != "examples":
270-
if len(file.parts) > parent_idx + 1:
271-
for prefix in package_folder_prefix:
272-
if file.parts[parent_idx].startswith(prefix):
273-
package_info["is_package"] = True
274-
if package_info["is_package"]:
275-
package_files.append(file)
276-
else:
277-
if file.name in IGNORE_PY:
278-
# print("Ignoring:", file.resolve())
279-
continue
280-
if file.parent == lib_path:
281-
py_files.append(file)
282-
283-
if package_files:
284-
package_info["module_name"] = package_files[0].relative_to(library_path).parent.name
285-
elif py_files:
286-
package_info["module_name"] = py_files[0].relative_to(library_path).name[:-3]
287-
else:
288-
package_info["module_name"] = None
283+
_detect_legacy_package_structure(
284+
package_info,
285+
package_files,
286+
py_files,
287+
glob_search,
288+
parent_idx,
289+
package_folder_prefix,
290+
lib_path,
291+
library_path,
292+
)
289293

290294
if len(py_files) > 1:
291295
raise ValueError(
@@ -307,6 +311,40 @@ def get_package_info(library_path, package_folder_prefix):
307311
return package_info
308312

309313

314+
def _detect_legacy_package_structure(
315+
package_info: dict,
316+
package_files: list[pathlib.Path],
317+
py_files: list[pathlib.Path],
318+
glob_search: list[pathlib.Path],
319+
parent_idx: int,
320+
package_folder_prefix: str,
321+
lib_path: pathlib.Path,
322+
library_path: str,
323+
) -> None:
324+
package_info["is_package"] = False
325+
for file in glob_search:
326+
if file.parts[parent_idx] != "examples":
327+
if len(file.parts) > parent_idx + 1:
328+
for prefix in package_folder_prefix:
329+
if file.parts[parent_idx].startswith(prefix):
330+
package_info["is_package"] = True
331+
if package_info["is_package"]:
332+
package_files.append(file)
333+
else:
334+
if file.name in IGNORE_PY:
335+
# print("Ignoring:", file.resolve())
336+
continue
337+
if file.parent == lib_path:
338+
py_files.append(file)
339+
340+
if package_files:
341+
package_info["module_name"] = package_files[0].relative_to(library_path).parent.name
342+
elif py_files:
343+
package_info["module_name"] = py_files[0].relative_to(library_path).name[:-3]
344+
else:
345+
package_info["module_name"] = None
346+
347+
310348
def library(
311349
library_path, output_directory, package_folder_prefix, mpy_cross=None, example_bundle=False
312350
):
@@ -327,33 +365,9 @@ def library(
327365
for filename in py_package_files:
328366
full_path = os.path.join(library_path, filename)
329367
output_file = output_directory / filename.relative_to(library_path)
330-
if filename.suffix == ".py":
331-
with tempfile.NamedTemporaryFile(delete=False, mode="w+") as temp_file:
332-
temp_file_name = temp_file.name
333-
try:
334-
_munge_to_temp(full_path, temp_file, library_version)
335-
temp_file.close()
336-
if mpy_cross and os.stat(temp_file.name).st_size != 0:
337-
output_file = output_file.with_suffix(".mpy")
338-
mpy_success = subprocess.call(
339-
[
340-
mpy_cross,
341-
"-o",
342-
output_file,
343-
"-s",
344-
str(filename.relative_to(library_path)),
345-
temp_file.name,
346-
]
347-
)
348-
if mpy_success != 0:
349-
raise RuntimeError("mpy-cross failed on", full_path)
350-
else:
351-
shutil.copyfile(temp_file_name, output_file)
352-
finally:
353-
os.remove(temp_file_name)
354-
else:
355-
shutil.copyfile(full_path, output_file)
356-
368+
_run_mpy_cross_on_mod(
369+
filename, full_path, output_file, mpy_cross, library_path, library_version
370+
)
357371
requirements_files = lib_path.glob("requirements.txt*")
358372
requirements_files = [f for f in requirements_files if f.stat().st_size > 0]
359373

@@ -383,3 +397,39 @@ def library(
383397

384398
os.makedirs(os.path.join(*output_file.split(os.path.sep)[:-1]), exist_ok=True)
385399
shutil.copyfile(full_path, output_file)
400+
401+
402+
def _run_mpy_cross_on_mod(
403+
filename: pathlib.Path,
404+
full_path: str,
405+
output_file: str,
406+
mpy_cross: pathlib.Path | None,
407+
library_path: str,
408+
library_version: str,
409+
) -> None:
410+
if filename.suffix == ".py":
411+
with tempfile.NamedTemporaryFile(delete=False, mode="w+") as temp_file:
412+
temp_file_name = temp_file.name
413+
try:
414+
_munge_to_temp(full_path, temp_file, library_version)
415+
temp_file.close()
416+
if mpy_cross and os.stat(temp_file.name).st_size != 0:
417+
output_file = output_file.with_suffix(".mpy")
418+
mpy_success = subprocess.call(
419+
[
420+
mpy_cross,
421+
"-o",
422+
output_file,
423+
"-s",
424+
str(filename.relative_to(library_path)),
425+
temp_file.name,
426+
]
427+
)
428+
if mpy_success != 0:
429+
raise RuntimeError("mpy-cross failed on", full_path)
430+
else:
431+
shutil.copyfile(temp_file_name, output_file)
432+
finally:
433+
os.remove(temp_file_name)
434+
else:
435+
shutil.copyfile(full_path, output_file)

0 commit comments

Comments
 (0)