4040import tempfile
4141import platformdirs
4242
43+
4344@functools .cache
4445def _git_version ():
45- version_str = subprocess .check_output (["git" , "--version" ], encoding = "ascii" , errors = "replace" )
46+ version_str = subprocess .check_output (
47+ ["git" , "--version" ], encoding = "ascii" , errors = "replace"
48+ )
4649 version_str = re .search (r"([0-9]\.*)*[0-9]" , version_str ).group (0 )
4750 return tuple (int (part ) for part in version_str .split ("." ))
4851
52+
4953def git_filter_arg ():
5054 clone_supports_filter = (
5155 False if "NO_USE_CLONE_FILTER" in os .environ else _git_version () >= (2 , 36 , 0 )
@@ -56,68 +60,100 @@ def git_filter_arg():
5660 else :
5761 return []
5862
63+
5964# pyproject.toml `py_modules` values that are incorrect. These should all have PRs filed!
6065# and should be removed when the fixed version is incorporated in its respective bundle.
6166
62- pyproject_py_modules_blocklist = set ((
63- # community bundle
64- "at24mac_eeprom" ,
65- "p1am_200_helpers" ,
66- ))
67+ pyproject_py_modules_blocklist = set (
68+ (
69+ # community bundle
70+ "at24mac_eeprom" ,
71+ "p1am_200_helpers" ,
72+ )
73+ )
6774
6875if sys .version_info >= (3 , 11 ):
6976 from tomllib import loads as load_toml
7077else :
7178 from tomli import loads as load_toml
7279
73- mpy_cross_path = platformdirs .user_cache_path ("circuitpython-build-tools" , ensure_exists = True )
80+ mpy_cross_path = platformdirs .user_cache_path (
81+ "circuitpython-build-tools" , ensure_exists = True
82+ )
83+
7484
7585def load_pyproject_toml (lib_path : pathlib .Path ):
7686 try :
77- return load_toml ((lib_path / "pyproject.toml" ) .read_text (encoding = "utf-8" ))
87+ return load_toml ((lib_path / "pyproject.toml" ).read_text (encoding = "utf-8" ))
7888 except FileNotFoundError :
7989 print (f"No pyproject.toml in { lib_path } " )
8090 return {}
8191
92+
8293def get_nested (doc , * args , default = None ):
8394 for a in args :
84- if doc is None : return default
95+ if doc is None :
96+ return default
8597 try :
8698 doc = doc [a ]
8799 except (KeyError , IndexError ) as e :
88100 return default
89101 return doc
90102
103+
91104IGNORE_PY = ["setup.py" , "conf.py" , "__init__.py" ]
92105GLOB_PATTERNS = ["*.py" , "*.bin" ]
93106S3_MPY_PREFIX = "https://adafruit-circuit-python.s3.amazonaws.com/bin/mpy-cross"
94107
108+
95109def version_string (path = None , * , valid_semver = False ):
96110 version = None
97- tag = subprocess .run ('git describe --tags --exact-match' , shell = True , stdout = subprocess .PIPE , stderr = subprocess .PIPE , cwd = path )
111+ tag = subprocess .run (
112+ "git describe --tags --exact-match" ,
113+ shell = True ,
114+ stdout = subprocess .PIPE ,
115+ stderr = subprocess .PIPE ,
116+ cwd = path ,
117+ )
98118 if tag .returncode == 0 :
99119 version = tag .stdout .strip ().decode ("utf-8" , "strict" )
100120 else :
101- describe = subprocess .run ("git describe --tags --always" , shell = True , stdout = subprocess .PIPE , cwd = path )
102- describe = describe .stdout .strip ().decode ("utf-8" , "strict" ).rsplit ("-" , maxsplit = 2 )
121+ describe = subprocess .run (
122+ "git describe --tags --always" , shell = True , stdout = subprocess .PIPE , cwd = path
123+ )
124+ describe = (
125+ describe .stdout .strip ().decode ("utf-8" , "strict" ).rsplit ("-" , maxsplit = 2 )
126+ )
103127 if len (describe ) == 3 :
104128 tag , additional_commits , commitish = describe
105129 commitish = commitish [1 :]
106130 else :
107131 tag = "0.0.0"
108- commit_count = subprocess .run ("git rev-list --count HEAD" , shell = True , stdout = subprocess .PIPE , cwd = path )
132+ commit_count = subprocess .run (
133+ "git rev-list --count HEAD" ,
134+ shell = True ,
135+ stdout = subprocess .PIPE ,
136+ cwd = path ,
137+ )
109138 additional_commits = commit_count .stdout .strip ().decode ("utf-8" , "strict" )
110139 commitish = describe [0 ]
111140 if valid_semver :
112141 version_info = semver .parse_version_info (tag )
113142 if not version_info .prerelease :
114- version = semver .bump_patch (tag ) + "-alpha.0.plus." + additional_commits + "+" + commitish
143+ version = (
144+ semver .bump_patch (tag )
145+ + "-alpha.0.plus."
146+ + additional_commits
147+ + "+"
148+ + commitish
149+ )
115150 else :
116151 version = tag + ".plus." + additional_commits + "+" + commitish
117152 else :
118153 version = commitish
119154 return version
120155
156+
121157def mpy_cross (version , quiet = False ):
122158 circuitpython_tag = version ["tag" ]
123159 name = version ["name" ]
@@ -130,16 +166,20 @@ def mpy_cross(version, quiet=False):
130166 # Try to pull from S3
131167 uname = platform .uname ()
132168 s3_url = None
133- if uname [0 ].title () == ' Linux' and uname [4 ].lower () in (' amd64' , ' x86_64' ):
169+ if uname [0 ].title () == " Linux" and uname [4 ].lower () in (" amd64" , " x86_64" ):
134170 s3_url = f"{ S3_MPY_PREFIX } /linux-amd64/mpy-cross-linux-amd64-{ circuitpython_tag } .static"
135- elif uname [0 ].title () == ' Linux' and uname [4 ].lower () == ' armv7l' :
171+ elif uname [0 ].title () == " Linux" and uname [4 ].lower () == " armv7l" :
136172 s3_url = f"{ S3_MPY_PREFIX } /linux-raspbian/mpy-cross-linux-raspbian-{ circuitpython_tag } .static-raspbian"
137- elif uname [0 ].title () == ' Darwin' :
173+ elif uname [0 ].title () == " Darwin" :
138174 s3_url = f"{ S3_MPY_PREFIX } /macos/mpy-cross-macos-{ circuitpython_tag } -universal"
139175 elif uname [0 ].title () == "Windows" and uname [4 ].lower () in ("amd64" , "x86_64" ):
140- s3_url = f"{ S3_MPY_PREFIX } /windows/mpy-cross-windows-{ circuitpython_tag } .static.exe"
176+ s3_url = (
177+ f"{ S3_MPY_PREFIX } /windows/mpy-cross-windows-{ circuitpython_tag } .static.exe"
178+ )
141179 elif not quiet :
142- print (f"Pre-built mpy-cross not available for sysname='{ uname [0 ]} ' release='{ uname [2 ]} ' machine='{ uname [4 ]} '." )
180+ print (
181+ f"Pre-built mpy-cross not available for sysname='{ uname [0 ]} ' release='{ uname [2 ]} ' machine='{ uname [4 ]} '."
182+ )
143183
144184 if s3_url is not None :
145185 if not quiet :
@@ -150,7 +190,10 @@ def mpy_cross(version, quiet=False):
150190 with open (mpy_cross_filename , "wb" ) as f :
151191 f .write (r .content )
152192 # Set the User Execute bit
153- os .chmod (mpy_cross_filename , os .stat (mpy_cross_filename )[0 ] | stat .S_IXUSR )
193+ os .chmod (
194+ mpy_cross_filename ,
195+ os .stat (mpy_cross_filename )[0 ] | stat .S_IXUSR ,
196+ )
154197 if not quiet :
155198 print (" FOUND" )
156199 return mpy_cross_filename
@@ -168,12 +211,26 @@ def mpy_cross(version, quiet=False):
168211
169212 build_dir = mpy_cross_path / f"build-circuitpython-{ circuitpython_tag } "
170213 if not os .path .isdir (build_dir ):
171- subprocess .check_call (["git" , "clone" , * git_filter_arg (), "-b" , circuitpython_tag , "https://github.com/adafruit/circuitpython.git" , build_dir ])
214+ subprocess .check_call (
215+ [
216+ "git" ,
217+ "clone" ,
218+ * git_filter_arg (),
219+ "-b" ,
220+ circuitpython_tag ,
221+ "https://github.com/adafruit/circuitpython.git" ,
222+ build_dir ,
223+ ]
224+ )
172225
173226 subprocess .check_call (["git" , "submodule" , "update" , "--recursive" ], cwd = build_dir )
174- subprocess .check_call ([sys .executable , "tools/ci_fetch_deps.py" , "mpy-cross" ], cwd = build_dir )
227+ subprocess .check_call (
228+ [sys .executable , "tools/ci_fetch_deps.py" , "mpy-cross" ], cwd = build_dir
229+ )
175230 subprocess .check_call (["make" , "clean" ], cwd = build_dir / "mpy-cross" )
176- subprocess .check_call (["make" , f"-j{ multiprocessing .cpu_count ()} " ], cwd = build_dir / "mpy-cross" )
231+ subprocess .check_call (
232+ ["make" , f"-j{ multiprocessing .cpu_count ()} " ], cwd = build_dir / "mpy-cross"
233+ )
177234
178235 mpy_built = build_dir / f"mpy-cross/build/mpy-cross{ ext } "
179236 if not os .path .exists (mpy_built ):
@@ -182,6 +239,7 @@ def mpy_cross(version, quiet=False):
182239 shutil .copy (mpy_built , mpy_cross_filename )
183240 return mpy_cross_filename
184241
242+
185243def _munge_to_temp (original_path , temp_file , library_version ):
186244 with open (original_path , "r" , encoding = "utf-8" ) as original_file :
187245 for line in original_file :
@@ -192,6 +250,7 @@ def _munge_to_temp(original_path, temp_file, library_version):
192250 print (line , file = temp_file )
193251 temp_file .flush ()
194252
253+
195254def get_package_info (library_path , package_folder_prefix ):
196255 lib_path = pathlib .Path (library_path )
197256 parent_idx = len (lib_path .parts )
@@ -203,18 +262,29 @@ def get_package_info(library_path, package_folder_prefix):
203262 glob_search .extend (list (lib_path .rglob (pattern )))
204263
205264 pyproject_toml = load_pyproject_toml (lib_path )
206- py_modules = get_nested (pyproject_toml , "tool" , "setuptools" , "py-modules" , default = [])
265+ py_modules = get_nested (
266+ pyproject_toml , "tool" , "setuptools" , "py-modules" , default = []
267+ )
207268 packages = get_nested (pyproject_toml , "tool" , "setuptools" , "packages" , default = [])
208- package_info ["description" ] = get_nested (pyproject_toml , "project" , "description" , default = "" )
269+ package_info ["description" ] = get_nested (
270+ pyproject_toml , "project" , "description" , default = ""
271+ )
209272
210- blocklisted = [name for name in py_modules if name in pyproject_py_modules_blocklist ]
273+ blocklisted = [
274+ name for name in py_modules if name in pyproject_py_modules_blocklist
275+ ]
211276
212277 if blocklisted :
213- print (f"{ lib_path } /settings.toml:1: { blocklisted [0 ]} blocklisted: not using metadata from pyproject.toml" )
278+ print (
279+ f"{ lib_path } /settings.toml:1: { blocklisted [0 ]} blocklisted: not using metadata from pyproject.toml"
280+ )
214281 py_modules = packages = ()
215282
216- example_files = [sub_path for sub_path in (lib_path / "examples" ).rglob ("*" )
217- if sub_path .is_file ()]
283+ example_files = [
284+ sub_path
285+ for sub_path in (lib_path / "examples" ).rglob ("*" )
286+ if sub_path .is_file ()
287+ ]
218288
219289 if packages and py_modules :
220290 raise ValueError ("Cannot specify both tool.setuptools.py-modules and .packages" )
@@ -223,17 +293,20 @@ def get_package_info(library_path, package_folder_prefix):
223293 if len (packages ) > 1 :
224294 raise ValueError ("Only a single package is supported" )
225295 package_name = packages [0 ]
226- #print(f"Using package name from pyproject.toml: {package_name}")
296+ # print(f"Using package name from pyproject.toml: {package_name}")
227297 package_info ["is_package" ] = True
228298 package_info ["module_name" ] = package_name
229- package_files = [sub_path for sub_path in (lib_path / package_name ).rglob ("*" )
230- if sub_path .is_file ()]
299+ package_files = [
300+ sub_path
301+ for sub_path in (lib_path / package_name ).rglob ("*" )
302+ if sub_path .is_file ()
303+ ]
231304
232305 elif py_modules :
233306 if len (py_modules ) > 1 :
234307 raise ValueError ("Only a single module is supported" )
235308 py_module = py_modules [0 ]
236- #print(f"Using module name from pyproject.toml: {py_module}")
309+ # print(f"Using module name from pyproject.toml: {py_module}")
237310 package_name = py_module
238311 package_info ["is_package" ] = False
239312 package_info ["module_name" ] = py_module
@@ -252,21 +325,27 @@ def get_package_info(library_path, package_folder_prefix):
252325 package_files .append (file )
253326 else :
254327 if file .name in IGNORE_PY :
255- #print("Ignoring:", file.resolve())
328+ # print("Ignoring:", file.resolve())
256329 continue
257330 if file .parent == lib_path :
258331 py_files .append (file )
259332
260333 if package_files :
261- package_info ["module_name" ] = package_files [0 ].relative_to (library_path ).parent .name
334+ package_info ["module_name" ] = (
335+ package_files [0 ].relative_to (library_path ).parent .name
336+ )
262337 elif py_files :
263- package_info ["module_name" ] = py_files [0 ].relative_to (library_path ).name [:- 3 ]
338+ package_info ["module_name" ] = (
339+ py_files [0 ].relative_to (library_path ).name [:- 3 ]
340+ )
264341 else :
265342 package_info ["module_name" ] = None
266343
267344 if len (py_files ) > 1 :
268- raise ValueError ("Multiple top level py files not allowed. Please put "
269- "them in a package or combine them into a single file." )
345+ raise ValueError (
346+ "Multiple top level py files not allowed. Please put "
347+ "them in a package or combine them into a single file."
348+ )
270349
271350 package_info ["package_files" ] = package_files
272351 package_info ["py_files" ] = py_files
@@ -281,21 +360,26 @@ def get_package_info(library_path, package_folder_prefix):
281360
282361 return package_info
283362
284- def library (library_path , output_directory , package_folder_prefix ,
285- mpy_cross = None , example_bundle = False ):
363+
364+ def library (
365+ library_path ,
366+ output_directory ,
367+ package_folder_prefix ,
368+ mpy_cross = None ,
369+ example_bundle = False ,
370+ ):
286371 lib_path = pathlib .Path (library_path )
287372 package_info = get_package_info (library_path , package_folder_prefix )
288373 py_package_files = package_info ["package_files" ] + package_info ["py_files" ]
289374 example_files = package_info ["example_files" ]
290375 module_name = package_info ["module_name" ]
291376
292377 for fn in py_package_files :
293- base_dir = os .path .join (output_directory ,
294- fn .relative_to (library_path ).parent )
378+ base_dir = os .path .join (output_directory , fn .relative_to (library_path ).parent )
295379 if not os .path .isdir (base_dir ):
296380 os .makedirs (base_dir )
297381
298- library_version = package_info [' version' ]
382+ library_version = package_info [" version" ]
299383
300384 if not example_bundle :
301385 for filename in py_package_files :
@@ -309,12 +393,16 @@ def library(library_path, output_directory, package_folder_prefix,
309393 temp_file .close ()
310394 if mpy_cross and os .stat (temp_file .name ).st_size != 0 :
311395 output_file = output_file .with_suffix (".mpy" )
312- mpy_success = subprocess .call ([
313- mpy_cross ,
314- "-o" , output_file ,
315- "-s" , str (filename .relative_to (library_path )),
316- temp_file .name
317- ])
396+ mpy_success = subprocess .call (
397+ [
398+ mpy_cross ,
399+ "-o" ,
400+ output_file ,
401+ "-s" ,
402+ str (filename .relative_to (library_path )),
403+ temp_file .name ,
404+ ]
405+ )
318406 if mpy_success != 0 :
319407 raise RuntimeError ("mpy-cross failed on" , full_path )
320408 else :
@@ -349,8 +437,9 @@ def library(library_path, output_directory, package_folder_prefix,
349437 relative_filename_parts = list (filename .relative_to (library_path ).parts )
350438 relative_filename_parts .insert (1 , library_path .split (os .path .sep )[- 1 ])
351439 final_relative_filename = os .path .join (* relative_filename_parts )
352- output_file = os .path .join (output_directory .replace ("/lib" , "/" ),
353- final_relative_filename )
440+ output_file = os .path .join (
441+ output_directory .replace ("/lib" , "/" ), final_relative_filename
442+ )
354443
355444 os .makedirs (os .path .join (* output_file .split (os .path .sep )[:- 1 ]), exist_ok = True )
356445 shutil .copyfile (full_path , output_file )
0 commit comments