Skip to content

Commit f877188

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.. I had to do some simple abstractions to reduce the complexity of a couple functions. Also, there were some long lines that were not addressed by #142. The rest was auto-fixed by `ruff check --fix` or format changes by `ruff format`.
1 parent da13980 commit f877188

4 files changed

Lines changed: 146 additions & 100 deletions

File tree

circuitpython_build_tools/build.py

Lines changed: 119 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,19 @@
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+
2323
import platformdirs
24+
import requests
25+
import semver
2426

2527

2628
@functools.cache
@@ -89,15 +91,19 @@ def version_string(path=None, *, valid_semver=False):
8991
tag = subprocess.run(
9092
"git describe --tags --exact-match",
9193
shell=True,
92-
stdout=subprocess.PIPE,
93-
stderr=subprocess.PIPE,
94+
capture_output=True,
9495
cwd=path,
96+
check=False, # error handled below
9597
)
9698
if tag.returncode == 0:
9799
version = tag.stdout.strip().decode("utf-8", "strict")
98100
else:
99101
describe = subprocess.run(
100-
"git describe --tags --always", shell=True, stdout=subprocess.PIPE, cwd=path
102+
"git describe --tags --always",
103+
shell=True,
104+
stdout=subprocess.PIPE,
105+
cwd=path,
106+
check=True, # Let exception propagate an error from git
101107
)
102108
describe = describe.stdout.strip().decode("utf-8", "strict").rsplit("-", maxsplit=2)
103109
if len(describe) == 3:
@@ -106,7 +112,11 @@ def version_string(path=None, *, valid_semver=False):
106112
else:
107113
tag = "0.0.0"
108114
commit_count = subprocess.run(
109-
"git rev-list --count HEAD", shell=True, stdout=subprocess.PIPE, cwd=path
115+
"git rev-list --count HEAD",
116+
shell=True,
117+
stdout=subprocess.PIPE,
118+
cwd=path,
119+
check=True, # Let exception propagate an error from git
110120
)
111121
additional_commits = commit_count.stdout.strip().decode("utf-8", "strict")
112122
commitish = describe[0]
@@ -135,17 +145,21 @@ def mpy_cross(version, quiet=False):
135145
# Try to pull from S3
136146
uname = platform.uname()
137147
s3_url = None
138-
if uname[0].title() == "Linux" and uname[4].lower() in ("amd64", "x86_64"):
148+
if uname[0].title() == "Linux" and uname[4].lower() in {"amd64", "x86_64"}:
139149
s3_url = f"{S3_MPY_PREFIX}/linux-amd64/mpy-cross-linux-amd64-{circuitpython_tag}.static"
140150
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"
151+
s3_url = (
152+
f"{S3_MPY_PREFIX}/linux-raspbian/mpy-cross-linux-raspbian-{circuitpython_tag}."
153+
"static-raspbian"
154+
)
142155
elif uname[0].title() == "Darwin":
143156
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"):
157+
elif uname[0].title() == "Windows" and uname[4].lower() in {"amd64", "x86_64"}:
145158
s3_url = f"{S3_MPY_PREFIX}/windows/mpy-cross-windows-{circuitpython_tag}.static.exe"
146159
elif not quiet:
147160
print(
148-
f"Pre-built mpy-cross not available for sysname='{uname[0]}' release='{uname[2]}' machine='{uname[4]}'."
161+
"Pre-built mpy-cross not available for",
162+
f"sysname='{uname[0]}' release='{uname[2]}' machine='{uname[4]}'.",
149163
)
150164

151165
if s3_url is not None:
@@ -201,13 +215,13 @@ def mpy_cross(version, quiet=False):
201215

202216

203217
def _munge_to_temp(original_path, temp_file, library_version):
204-
with open(original_path, "r", encoding="utf-8") as original_file:
218+
with open(original_path, encoding="utf-8") as original_file:
205219
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)
220+
ln = line.strip("\n")
221+
if ln.startswith("__version__"):
222+
ln = ln.replace("0.0.0-auto.0", library_version)
223+
ln = ln.replace("0.0.0+auto.0", library_version)
224+
print(ln, file=temp_file)
211225
temp_file.flush()
212226

213227

@@ -230,7 +244,8 @@ def get_package_info(library_path, package_folder_prefix):
230244

231245
if blocklisted:
232246
print(
233-
f"{lib_path}/settings.toml:1: {blocklisted[0]} blocklisted: not using metadata from pyproject.toml"
247+
f"{lib_path}/settings.toml:1: {blocklisted[0]}",
248+
"blocklisted: not using metadata from pyproject.toml",
234249
)
235250
py_modules = packages = ()
236251

@@ -241,7 +256,7 @@ def get_package_info(library_path, package_folder_prefix):
241256
if packages and py_modules:
242257
raise ValueError("Cannot specify both tool.setuptools.py-modules and .packages")
243258

244-
elif packages:
259+
if packages:
245260
if len(packages) > 1:
246261
raise ValueError("Only a single package is supported")
247262
package_name = packages[0]
@@ -263,29 +278,16 @@ def get_package_info(library_path, package_folder_prefix):
263278
py_files = [lib_path / f"{py_module}.py"]
264279

265280
else:
266-
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
281+
_detect_legacy_package_structure(
282+
package_info,
283+
package_files,
284+
py_files,
285+
glob_search,
286+
parent_idx,
287+
package_folder_prefix,
288+
lib_path,
289+
library_path,
290+
)
289291

290292
if len(py_files) > 1:
291293
raise ValueError(
@@ -307,6 +309,41 @@ def get_package_info(library_path, package_folder_prefix):
307309
return package_info
308310

309311

312+
def _detect_legacy_package_structure(
313+
package_info: dict,
314+
package_files: list[pathlib.Path],
315+
py_files: list[pathlib.Path],
316+
glob_search: list[pathlib.Path],
317+
parent_idx: int,
318+
package_folder_prefix: str,
319+
lib_path: pathlib.Path,
320+
library_path: pathlib.Path,
321+
) -> None:
322+
print(f"{lib_path}: Using legacy autodetection")
323+
package_info["is_package"] = False
324+
for file in glob_search:
325+
if file.parts[parent_idx] != "examples":
326+
if len(file.parts) > parent_idx + 1:
327+
for prefix in package_folder_prefix:
328+
if file.parts[parent_idx].startswith(prefix):
329+
package_info["is_package"] = True
330+
if package_info["is_package"]:
331+
package_files.append(file)
332+
else:
333+
if file.name in IGNORE_PY:
334+
# print("Ignoring:", file.resolve())
335+
continue
336+
if file.parent == lib_path:
337+
py_files.append(file)
338+
339+
if package_files:
340+
package_info["module_name"] = package_files[0].relative_to(library_path).parent.name
341+
elif py_files:
342+
package_info["module_name"] = py_files[0].relative_to(library_path).name[:-3]
343+
else:
344+
package_info["module_name"] = None
345+
346+
310347
def library(
311348
library_path, output_directory, package_folder_prefix, mpy_cross=None, example_bundle=False
312349
):
@@ -327,33 +364,9 @@ def library(
327364
for filename in py_package_files:
328365
full_path = os.path.join(library_path, filename)
329366
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-
367+
_run_mpy_cross_on_mod(
368+
filename, full_path, output_file, mpy_cross, library_path, library_version
369+
)
357370
requirements_files = lib_path.glob("requirements.txt*")
358371
requirements_files = [f for f in requirements_files if f.stat().st_size > 0]
359372

@@ -383,3 +396,39 @@ def library(
383396

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

0 commit comments

Comments
 (0)