kopia lustrzana https://github.com/micropython/micropython
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 <jim.mussared@gmail.com>pull/13227/head
rodzic
5552896ca8
commit
5d28bb4adb
|
@ -194,6 +194,8 @@ class ManifestFile:
|
||||||
self._visited = set()
|
self._visited = set()
|
||||||
# Stack of metadata for each level.
|
# Stack of metadata for each level.
|
||||||
self._metadata = [ManifestPackageMetadata()]
|
self._metadata = [ManifestPackageMetadata()]
|
||||||
|
# Registered external libraries.
|
||||||
|
self._libraries = {}
|
||||||
|
|
||||||
def _resolve_path(self, path):
|
def _resolve_path(self, path):
|
||||||
# Convert path to an absolute path, applying variable substitutions.
|
# Convert path to an absolute path, applying variable substitutions.
|
||||||
|
@ -208,6 +210,7 @@ class ManifestFile:
|
||||||
"metadata": self.metadata,
|
"metadata": self.metadata,
|
||||||
"include": self.include,
|
"include": self.include,
|
||||||
"require": self.require,
|
"require": self.require,
|
||||||
|
"add_library": self.add_library,
|
||||||
"package": self.package,
|
"package": self.package,
|
||||||
"module": self.module,
|
"module": self.module,
|
||||||
"options": IncludeOptions(**kwargs),
|
"options": IncludeOptions(**kwargs),
|
||||||
|
@ -388,14 +391,25 @@ class ManifestFile:
|
||||||
if is_require:
|
if is_require:
|
||||||
self._metadata.pop()
|
self._metadata.pop()
|
||||||
|
|
||||||
def require(self, name, version=None, unix_ffi=False, pypi=None, **kwargs):
|
def _require_from_path(self, library_path, name, version, extra_kwargs):
|
||||||
|
for root, dirnames, filenames in os.walk(library_path):
|
||||||
|
if os.path.basename(root) == name and "manifest.py" in filenames:
|
||||||
|
self.include(root, is_require=True, **extra_kwargs)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def require(self, name, version=None, unix_ffi=False, pypi=None, library=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Require a module by name from micropython-lib.
|
Require a package by name from micropython-lib.
|
||||||
|
|
||||||
Optionally specify unix_ffi=True to use a module from the unix-ffi directory.
|
Optionally specify unix_ffi=True to use a module from the unix-ffi directory.
|
||||||
|
|
||||||
Optionally specify pipy="package-name" to indicate that this should
|
Optionally specify pipy="package-name" to indicate that this should
|
||||||
use the named package from PyPI when building for CPython.
|
use the named package from PyPI when building for CPython.
|
||||||
|
|
||||||
|
Optionally specify library="name" to reference a package from a
|
||||||
|
library that has been previously registered with add_library(). Otherwise
|
||||||
|
micropython-lib will be used.
|
||||||
"""
|
"""
|
||||||
self._metadata[-1].check_initialised(self._mode)
|
self._metadata[-1].check_initialised(self._mode)
|
||||||
|
|
||||||
|
@ -406,27 +420,46 @@ class ManifestFile:
|
||||||
self._pypi_dependencies.append(pypi)
|
self._pypi_dependencies.append(pypi)
|
||||||
return
|
return
|
||||||
|
|
||||||
if self._path_vars["MPY_LIB_DIR"]:
|
if library is not None:
|
||||||
|
# Find package in external library.
|
||||||
|
if library not in self._libraries:
|
||||||
|
raise ValueError("Unknown library '{}' for require('{}').".format(library, name))
|
||||||
|
library_path = self._libraries[library]
|
||||||
|
# Search for {library_path}/**/{name}/manifest.py.
|
||||||
|
if not self._require_from_path(library_path, name, version, kwargs):
|
||||||
|
raise ValueError(
|
||||||
|
"Package '{}' not found in external library '{}' ({}).".format(
|
||||||
|
name, library, library_path
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif self._path_vars["MPY_LIB_DIR"]:
|
||||||
|
# Find package in micropython-lib, in one of the three top-level directories.
|
||||||
lib_dirs = ["micropython", "python-stdlib", "python-ecosys"]
|
lib_dirs = ["micropython", "python-stdlib", "python-ecosys"]
|
||||||
if unix_ffi:
|
if unix_ffi:
|
||||||
# Search unix-ffi only if unix_ffi=True, and make unix-ffi modules
|
# Additionally search unix-ffi only if unix_ffi=True, and make unix-ffi modules
|
||||||
# take precedence.
|
# take precedence.
|
||||||
lib_dirs = ["unix-ffi"] + lib_dirs
|
lib_dirs = ["unix-ffi"] + lib_dirs
|
||||||
|
|
||||||
for lib_dir in lib_dirs:
|
for lib_dir in lib_dirs:
|
||||||
# Search for {lib_dir}/**/{name}/manifest.py.
|
# Search for {lib_dir}/**/{name}/manifest.py.
|
||||||
for root, dirnames, filenames in os.walk(
|
if self._require_from_path(
|
||||||
os.path.join(self._path_vars["MPY_LIB_DIR"], lib_dir)
|
os.path.join(self._path_vars["MPY_LIB_DIR"], lib_dir), name, version, kwargs
|
||||||
):
|
):
|
||||||
if os.path.basename(root) == name and "manifest.py" in filenames:
|
return
|
||||||
self.include(root, is_require=True, **kwargs)
|
|
||||||
return
|
|
||||||
|
|
||||||
raise ValueError("Library not found in local micropython-lib: {}".format(name))
|
raise ValueError("Package '{}' not found in local micropython-lib.".format(name))
|
||||||
else:
|
else:
|
||||||
# TODO: HTTP request to obtain URLs from manifest.json.
|
# TODO: HTTP request to obtain URLs from manifest.json.
|
||||||
raise ValueError("micropython-lib not available for require('{}').", name)
|
raise ValueError("micropython-lib not available for require('{}').", name)
|
||||||
|
|
||||||
|
def add_library(self, library, library_path):
|
||||||
|
"""
|
||||||
|
Register the path to an external named library.
|
||||||
|
|
||||||
|
This allows require("name", library="library") to find packages in that library.
|
||||||
|
"""
|
||||||
|
self._libraries[library] = self._resolve_path(library_path)
|
||||||
|
|
||||||
def package(self, package_path, files=None, base_path=".", opt=None):
|
def package(self, package_path, files=None, base_path=".", opt=None):
|
||||||
"""
|
"""
|
||||||
Define a package, optionally restricting to a set of files.
|
Define a package, optionally restricting to a set of files.
|
||||||
|
|
Ładowanie…
Reference in New Issue