import inspect import warnings from typing import Any, Dict, List, Optional, Tuple, Union from .generator import Generator from .providers import BaseProvider from .proxy import Faker class Documentor: def __init__(self, generator: Union[Generator, Faker]) -> None: """ :param generator: a localized Generator with providers filled, for which to write the documentation :type generator: faker.Generator() """ self.generator = generator self.max_name_len: int = 0 self.already_generated: List[str] = [] def get_formatters( self, locale: Optional[str] = None, excludes: Optional[List[str]] = None, **kwargs: Any, ) -> List[Tuple[BaseProvider, Dict[str, str]]]: self.max_name_len = 0 self.already_generated = [] if excludes is None else excludes[:] formatters = [] providers: List[BaseProvider] = self.generator.get_providers() for provider in providers[::-1]: # reverse if locale and provider.__lang__ and provider.__lang__ != locale: continue formatters.append( (provider, self.get_provider_formatters(provider, **kwargs)), ) return formatters def get_provider_formatters( self, provider: BaseProvider, prefix: str = "fake.", with_args: bool = True, with_defaults: bool = True, ) -> Dict[str, str]: formatters = {} for name, method in inspect.getmembers(provider, inspect.ismethod): # skip 'private' method and inherited methods if name.startswith("_") or name in self.already_generated: continue arguments = [] faker_args: List[str] = [] faker_kwargs = {} if name == "binary": faker_kwargs["length"] = 1024 elif name in ["zip", "tar"]: faker_kwargs.update( { "uncompressed_size": 1024, "min_file_size": 512, } ) if with_args: # retrieve all parameter argspec = inspect.getfullargspec(method) lst = [x for x in argspec.args if x not in ["self", "cls"]] for i, arg in enumerate(lst): if argspec.defaults and with_defaults: try: default = argspec.defaults[i] if isinstance(default, str): default = repr(default) else: # TODO check default type default = f"{default}" arg = f"{arg}={default}" except IndexError: pass arguments.append(arg) if with_args == "first": break if with_args != "first": if argspec.varargs: arguments.append("*" + argspec.varargs) if argspec.varkw: arguments.append("**" + argspec.varkw) # build fake method signature signature = f"{prefix}{name}({', '.join(arguments)})" try: # make a fake example example = self.generator.format(name, *faker_args, **faker_kwargs) except (AttributeError, ValueError) as e: warnings.warn(str(e)) continue formatters[signature] = example self.max_name_len = max(self.max_name_len, len(signature)) self.already_generated.append(name) return formatters @staticmethod def get_provider_name(provider_class: BaseProvider) -> str: return provider_class.__provider__