Skip to content

Commit 5d28bb4

Browse files
jimmodpgeorge
authored andcommitted
tools/manifestfile.py: Add support for external libraries.
This adds a `add_library(name, path)` method for use in manifest.py that allows registering an external path (e.g. to another repo) by name. This name can then be passed to `require("package", library="name")` to reference packages in that repo/library rather than micropython-lib. Within the external library, `require()` continues to work as normal (referencing micropython-lib) by default, but they can also specify the library name to require another package from that repo/library. Signed-off-by: Jim Mussared <[email protected]>
1 parent 5552896 commit 5d28bb4

File tree

1 file changed

+43
-10
lines changed

1 file changed

+43
-10
lines changed

tools/manifestfile.py

+43-10
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,8 @@ def __init__(self, mode, path_vars=None):
194194
self._visited = set()
195195
# Stack of metadata for each level.
196196
self._metadata = [ManifestPackageMetadata()]
197+
# Registered external libraries.
198+
self._libraries = {}
197199

198200
def _resolve_path(self, path):
199201
# Convert path to an absolute path, applying variable substitutions.
@@ -208,6 +210,7 @@ def _manifest_globals(self, kwargs):
208210
"metadata": self.metadata,
209211
"include": self.include,
210212
"require": self.require,
213+
"add_library": self.add_library,
211214
"package": self.package,
212215
"module": self.module,
213216
"options": IncludeOptions(**kwargs),
@@ -388,14 +391,25 @@ def include(self, manifest_path, is_require=False, **kwargs):
388391
if is_require:
389392
self._metadata.pop()
390393

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):
392402
"""
393-
Require a module by name from micropython-lib.
403+
Require a package by name from micropython-lib.
394404
395405
Optionally specify unix_ffi=True to use a module from the unix-ffi directory.
396406
397407
Optionally specify pipy="package-name" to indicate that this should
398408
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.
399413
"""
400414
self._metadata[-1].check_initialised(self._mode)
401415

@@ -406,27 +420,46 @@ def require(self, name, version=None, unix_ffi=False, pypi=None, **kwargs):
406420
self._pypi_dependencies.append(pypi)
407421
return
408422

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.
410437
lib_dirs = ["micropython", "python-stdlib", "python-ecosys"]
411438
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
413440
# take precedence.
414441
lib_dirs = ["unix-ffi"] + lib_dirs
415442

416443
for lib_dir in lib_dirs:
417444
# 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
420447
):
421-
if os.path.basename(root) == name and "manifest.py" in filenames:
422-
self.include(root, is_require=True, **kwargs)
423-
return
448+
return
424449

425-
raise ValueError("Library not found in local micropython-lib: {}".format(name))
450+
raise ValueError("Package '{}' not found in local micropython-lib.".format(name))
426451
else:
427452
# TODO: HTTP request to obtain URLs from manifest.json.
428453
raise ValueError("micropython-lib not available for require('{}').", name)
429454

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+
430463
def package(self, package_path, files=None, base_path=".", opt=None):
431464
"""
432465
Define a package, optionally restricting to a set of files.

0 commit comments

Comments
 (0)