| """Utilities to get where we should write namespace pkg paths.""" | |
| load("@bazel_skylib//rules:copy_file.bzl", "copy_file") | |
| _ext = struct( | |
| py = ".py", | |
| pyd = ".pyd", | |
| so = ".so", | |
| pyc = ".pyc", | |
| ) | |
| _TEMPLATE = Label("//python/private/pypi:namespace_pkg_tmpl.py") | |
| def _add_all(dirname, dirs): | |
| dir_path = "." | |
| for dir_name in dirname.split("/"): | |
| dir_path = "{}/{}".format(dir_path, dir_name) | |
| dirs[dir_path[2:]] = None | |
| def get_files(*, srcs, ignored_dirnames = [], root = None): | |
| """Get the list of filenames to write the namespace pkg files. | |
| Args: | |
| srcs: {type}`src` a list of files to be passed to {bzl:obj}`py_library` | |
| as `srcs` and `data`. This is usually a result of a {obj}`glob`. | |
| ignored_dirnames: {type}`str` a list of patterns to ignore. | |
| root: {type}`str` the prefix to use as the root. | |
| Returns: | |
| {type}`src` a list of paths to write the namespace pkg `__init__.py` file. | |
| """ | |
| dirs = {} | |
| ignored = {i: None for i in ignored_dirnames} | |
| if root: | |
| _add_all(root, ignored) | |
| for file in srcs: | |
| dirname, _, filename = file.rpartition("/") | |
| if filename == "__init__.py": | |
| ignored[dirname] = None | |
| dirname, _, _ = dirname.rpartition("/") | |
| elif filename.endswith(_ext.py): | |
| pass | |
| elif filename.endswith(_ext.pyc): | |
| pass | |
| elif filename.endswith(_ext.pyd): | |
| pass | |
| elif filename.endswith(_ext.so): | |
| pass | |
| else: | |
| continue | |
| if dirname in dirs or not dirname: | |
| continue | |
| _add_all(dirname, dirs) | |
| return sorted([d for d in dirs if d not in ignored]) | |
| def create_inits(*, srcs, ignored_dirnames = [], root = None, copy_file = copy_file, **kwargs): | |
| """Create init files and return the list to be included `py_library` srcs. | |
| Args: | |
| srcs: {type}`src` a list of files to be passed to {bzl:obj}`py_library` | |
| as `srcs` and `data`. This is usually a result of a {obj}`glob`. | |
| ignored_dirnames: {type}`str` a list of patterns to ignore. | |
| root: {type}`str` the prefix to use as the root. | |
| copy_file: the `copy_file` rule to copy files in build context. | |
| **kwargs: passed to {obj}`copy_file`. | |
| Returns: | |
| {type}`list[str]` to be included as part of `py_library`. | |
| """ | |
| ret = [] | |
| for i, out in enumerate(get_files(srcs = srcs, ignored_dirnames = ignored_dirnames, root = root)): | |
| src = "{}/__init__.py".format(out) | |
| ret.append(src) | |
| copy_file( | |
| # For the target name, use a number instead of trying to convert an output | |
| # path into a valid label. | |
| name = "_cp_{}_namespace".format(i), | |
| src = _TEMPLATE, | |
| out = src, | |
| **kwargs | |
| ) | |
| return ret |