@@ -194,6 +194,8 @@ def __init__(self, mode, path_vars=None):
194
194
self ._visited = set ()
195
195
# Stack of metadata for each level.
196
196
self ._metadata = [ManifestPackageMetadata ()]
197
+ # Registered external libraries.
198
+ self ._libraries = {}
197
199
198
200
def _resolve_path (self , path ):
199
201
# Convert path to an absolute path, applying variable substitutions.
@@ -208,6 +210,7 @@ def _manifest_globals(self, kwargs):
208
210
"metadata" : self .metadata ,
209
211
"include" : self .include ,
210
212
"require" : self .require ,
213
+ "add_library" : self .add_library ,
211
214
"package" : self .package ,
212
215
"module" : self .module ,
213
216
"options" : IncludeOptions (** kwargs ),
@@ -388,14 +391,25 @@ def include(self, manifest_path, is_require=False, **kwargs):
388
391
if is_require :
389
392
self ._metadata .pop ()
390
393
391
- def require (self , name , version = None , unix_ffi = False , pypi = None , ** kwargs ):
394
+ def _require_from_path (self , library_path , name , version , extra_kwargs ):
395
+ for root , dirnames , filenames in os .walk (library_path ):
396
+ if os .path .basename (root ) == name and "manifest.py" in filenames :
397
+ self .include (root , is_require = True , ** extra_kwargs )
398
+ return True
399
+ return False
400
+
401
+ def require (self , name , version = None , unix_ffi = False , pypi = None , library = None , ** kwargs ):
392
402
"""
393
- Require a module by name from micropython-lib.
403
+ Require a package by name from micropython-lib.
394
404
395
405
Optionally specify unix_ffi=True to use a module from the unix-ffi directory.
396
406
397
407
Optionally specify pipy="package-name" to indicate that this should
398
408
use the named package from PyPI when building for CPython.
409
+
410
+ Optionally specify library="name" to reference a package from a
411
+ library that has been previously registered with add_library(). Otherwise
412
+ micropython-lib will be used.
399
413
"""
400
414
self ._metadata [- 1 ].check_initialised (self ._mode )
401
415
@@ -406,27 +420,46 @@ def require(self, name, version=None, unix_ffi=False, pypi=None, **kwargs):
406
420
self ._pypi_dependencies .append (pypi )
407
421
return
408
422
409
- if self ._path_vars ["MPY_LIB_DIR" ]:
423
+ if library is not None :
424
+ # Find package in external library.
425
+ if library not in self ._libraries :
426
+ raise ValueError ("Unknown library '{}' for require('{}')." .format (library , name ))
427
+ library_path = self ._libraries [library ]
428
+ # Search for {library_path}/**/{name}/manifest.py.
429
+ if not self ._require_from_path (library_path , name , version , kwargs ):
430
+ raise ValueError (
431
+ "Package '{}' not found in external library '{}' ({})." .format (
432
+ name , library , library_path
433
+ )
434
+ )
435
+ elif self ._path_vars ["MPY_LIB_DIR" ]:
436
+ # Find package in micropython-lib, in one of the three top-level directories.
410
437
lib_dirs = ["micropython" , "python-stdlib" , "python-ecosys" ]
411
438
if unix_ffi :
412
- # Search unix-ffi only if unix_ffi=True, and make unix-ffi modules
439
+ # Additionally search unix-ffi only if unix_ffi=True, and make unix-ffi modules
413
440
# take precedence.
414
441
lib_dirs = ["unix-ffi" ] + lib_dirs
415
442
416
443
for lib_dir in lib_dirs :
417
444
# Search for {lib_dir}/**/{name}/manifest.py.
418
- for root , dirnames , filenames in os . walk (
419
- os .path .join (self ._path_vars ["MPY_LIB_DIR" ], lib_dir )
445
+ if self . _require_from_path (
446
+ os .path .join (self ._path_vars ["MPY_LIB_DIR" ], lib_dir ), name , version , kwargs
420
447
):
421
- if os .path .basename (root ) == name and "manifest.py" in filenames :
422
- self .include (root , is_require = True , ** kwargs )
423
- return
448
+ return
424
449
425
- raise ValueError ("Library not found in local micropython-lib: {} " .format (name ))
450
+ raise ValueError ("Package '{}' not found in local micropython-lib. " .format (name ))
426
451
else :
427
452
# TODO: HTTP request to obtain URLs from manifest.json.
428
453
raise ValueError ("micropython-lib not available for require('{}')." , name )
429
454
455
+ def add_library (self , library , library_path ):
456
+ """
457
+ Register the path to an external named library.
458
+
459
+ This allows require("name", library="library") to find packages in that library.
460
+ """
461
+ self ._libraries [library ] = self ._resolve_path (library_path )
462
+
430
463
def package (self , package_path , files = None , base_path = "." , opt = None ):
431
464
"""
432
465
Define a package, optionally restricting to a set of files.
0 commit comments