1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
#!/usr/bin/env python3
# Copyright (c) Facebook, Inc. and its affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
#
from importlib import import_module
import pkgutil
import types
import typing as t
def _walk_module(module: types.ModuleType):
for attr_name in dir(module):
# filter out private members
if not attr_name.startswith("_"):
member = getattr(module, attr_name)
if hasattr(member, "__command"):
yield member
def _walk_package(name, path) -> t.List[types.FunctionType]:
packages = pkgutil.walk_packages(path, prefix=f"{name}.")
for importer, modname, ispkg in packages:
loaded = import_module(modname)
if not ispkg:
yield from _walk_module(loaded)
def load_commands(base_package) -> None:
"""
Loads all commands defined in a loaded python package object. This function
recursively look for classes and function annotated with @command and return
a list of these objects.
"""
if base_package is not None:
path = None
if hasattr(base_package, "__path__"):
path = getattr(base_package, "__path__")
else:
path = getattr(base_package, "__file__")
assert path is not None
yield from _walk_package(base_package.__name__, path)
|