119 lines
3.9 KiB
Python
119 lines
3.9 KiB
Python
|
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__
|