PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/baredoc.py |
""" Baredoc walks the installed module and state directories and generates dictionaries and lists of the function names and their arguments. .. versionadded:: 3001 """ import ast import itertools import logging import os from typing import Dict, List import salt.utils.doc import salt.utils.files from salt.exceptions import ArgumentValueError from salt.utils.odict import OrderedDict log = logging.getLogger(__name__) def _get_module_name(tree, filename: str) -> str: """ Returns the value of __virtual__ if found. Otherwise, returns filename """ module_name = os.path.basename(filename).split(".")[0] assignments = [node for node in tree.body if isinstance(node, ast.Assign)] for assign in assignments: try: if assign.targets[0].id == "__virtualname__": module_name = assign.value.s except AttributeError: pass return module_name def _get_func_aliases(tree) -> Dict: """ Get __func_alias__ dict for mapping function names """ fun_aliases = {} assignments = [node for node in tree.body if isinstance(node, ast.Assign)] for assign in assignments: try: if assign.targets[0].id == "__func_alias__": for key, value in itertools.zip_longest( assign.value.keys, assign.value.values ): fun_aliases.update({key.s: value.s}) except AttributeError: pass return fun_aliases def _get_args(function: str) -> Dict: """ Given a function def, returns arguments and defaults """ # Generate list of arguments arg_strings = [] list_of_arguments = function.args.args if list_of_arguments: for arg in list_of_arguments: arg_strings.append(arg.arg) # Generate list of arg defaults # Values are only returned for populated items arg_default_strings = [] list_arg_defaults = function.args.defaults if list_arg_defaults: for arg_default in list_arg_defaults: if isinstance(arg_default, ast.NameConstant): arg_default_strings.append(arg_default.value) elif isinstance(arg_default, ast.Str): arg_default_strings.append(arg_default.s) elif isinstance(arg_default, ast.Num): arg_default_strings.append(arg_default.n) # Since only some args may have default values, need to zip in reverse order backwards_args = OrderedDict( itertools.zip_longest(reversed(arg_strings), reversed(arg_default_strings)) ) ordered_args = OrderedDict(reversed(list(backwards_args.items()))) try: ordered_args["args"] = function.args.vararg.arg except AttributeError: pass try: ordered_args["kwargs"] = function.args.kwarg.arg except AttributeError: pass return ordered_args def _parse_module_docs(module_path, mod_name=None): """ Gather module docstrings or module.function doc string if requested """ ret = {} with salt.utils.files.fopen(module_path, "r", encoding="utf8") as cur_file: tree = ast.parse(cur_file.read()) module_name = _get_module_name(tree, module_path) if not mod_name or "." not in mod_name: # Return top level docs for the module if a function is not requested ret[module_name] = ast.get_docstring(tree) fun_aliases = _get_func_aliases(tree) functions = [node for node in tree.body if isinstance(node, ast.FunctionDef)] for fn in functions: doc_string = ast.get_docstring(fn) if not fn.name.startswith("_"): function_name = fn.name if fun_aliases: # Translate name to __func_alias__ version for k, v in fun_aliases.items(): if fn.name == k: function_name = v if mod_name and "." in mod_name: if function_name == mod_name.split(".")[1]: ret[f"{module_name}.{function_name}"] = doc_string else: ret[f"{module_name}.{function_name}"] = doc_string return salt.utils.doc.strip_rst(ret) def _parse_module_functions(module_py: str, return_type: str) -> Dict: """ Parse module files for proper module_name and function name, then gather functions and possibly arguments """ ret = {} with salt.utils.files.fopen(module_py, "r", encoding="utf8") as cur_file: tree = ast.parse(cur_file.read()) module_name = _get_module_name(tree, module_py) fun_aliases = _get_func_aliases(tree) functions = [node for node in tree.body if isinstance(node, ast.FunctionDef)] func_list = [] for fn in functions: if not fn.name.startswith("_"): function_name = fn.name if fun_aliases: # Translate name to __func_alias__ version for k, v in fun_aliases.items(): if fn.name == k: function_name = v args = _get_args(fn) if return_type == "names": func_list.append(function_name) else: # return_type == args so gather and return all args fun_entry = {} fun_entry[function_name] = args func_list.append(fun_entry) ret[module_name] = func_list return ret def _get_files(name=False, type="states", return_type="args") -> List: """ Determine if modules/states directories or files are requested return_type = names == names_only=True return_type = args == names_only=Fals return_type = docs """ dirs = [] found_files = [] if type == "modules": dirs.append(os.path.join(__opts__["extension_modules"], "modules")) dirs.append(os.path.join(__grains__["saltpath"], "modules")) elif type == "states": dirs.append(os.path.join(__opts__["extension_modules"], "states")) dirs.append(os.path.join(__grains__["saltpath"], "states")) if name: if "." in name: if return_type != "docs": # Only docs support module.function syntax raise ArgumentValueError("Function name given") else: name = name.split(".")[0] for dir in dirs: # Process custom dirs first so custom results are returned file_path = os.path.join(dir, name + ".py") if os.path.exists(file_path): found_files.append(file_path) return found_files else: for dir in reversed(dirs): # Process custom dirs last so they are displayed try: for module_py in os.listdir(dir): if module_py.endswith(".py") and module_py != "__init__.py": found_files.append(os.path.join(dir, module_py)) except FileNotFoundError: pass return found_files def list_states(name=False, names_only=False): """ Walk the Salt install tree for state modules and return a dictionary or a list of their functions as well as their arguments. :param name: specify a specific module to list. If not specified, all modules will be listed. :param names_only: Return only a list of the callable functions instead of a dictionary with arguments CLI Example: (example truncated for brevity) .. code-block:: bash salt myminion baredoc.list_states myminion: ---------- [...] at: - present: name: null timespec: null tag: null user: null job: null unique_tag: false - absent: name: null jobid: null kwargs: kwargs - watch: name: null timespec: null tag: null user: null job: null unique_tag: false - mod_watch: name: null kwargs: kwargs [...] """ ret = {} if names_only: return_type = "names" else: return_type = "args" found_files = _get_files(name, type="states", return_type=return_type) for file in found_files: ret.update(_parse_module_functions(file, return_type=return_type)) return OrderedDict(sorted(ret.items())) def list_modules(name=False, names_only=False): """ Walk the Salt install tree for execution modules and return a dictionary or a list of their functions as well as their arguments. :param name: specify a specific module to list. If not specified, all modules will be listed. :param names_only: Return only a list of the callable functions instead of a dictionary with arguments CLI Example: .. code-block:: bash salt myminion baredoc.list_modules myminion: ---------- [...] at: - atq: tag: null - atrm: args: args - at: args: args kwargs: kwargs - atc: jobid: null - jobcheck: kwargs: kwargs [...] """ ret = {} if names_only: return_type = "names" else: return_type = "args" found_files = _get_files(name, type="modules", return_type=return_type) for file in found_files: ret.update(_parse_module_functions(file, return_type=return_type)) return OrderedDict(sorted(ret.items())) def state_docs(*names): """ Return the docstrings for all state modules. Optionally, specify a state module or a function to narrow the selection. :param name: specify a specific module to list. CLI Example: .. code-block:: bash salt myminion baredoc.state_docs at """ return_type = "docs" ret = {} if names: for name in names: file = _get_files(name, type="states", return_type=return_type)[0] ret.update(_parse_module_docs(file, name)) return OrderedDict(sorted(ret.items())) else: found_files = [] found_files.extend(_get_files(type="states", return_type=return_type)) for file in found_files: ret.update(_parse_module_docs(file)) return OrderedDict(sorted(ret.items())) def module_docs(*names): """ Return the docstrings for all modules. Optionally, specify a module or a function to narrow the selection. :param name: specify a specific module to list. CLI Example: .. code-block:: bash salt myminion baredoc.module_docs """ return_type = "docs" ret = {} if names: for name in names: file = _get_files(name, type="modules", return_type=return_type)[0] ret.update(_parse_module_docs(file, name)) return OrderedDict(sorted(ret.items())) else: found_files = [] found_files.extend(_get_files(type="modules", return_type=return_type)) for file in found_files: ret.update(_parse_module_docs(file)) return OrderedDict(sorted(ret.items()))