docs: Initial reference manual generator

pull/8960/head
Daniel Mensinger 4 years ago
parent 3feaea6b29
commit ad65a699f9
No known key found for this signature in database
GPG Key ID: 54DD94C131E277D4
  1. 27
      docs/genrefman.py
  2. 0
      docs/refman/__init__.py
  3. 67
      docs/refman/generatorbase.py
  4. 88
      docs/refman/generatorprint.py
  5. 215
      docs/refman/loaderbase.py
  6. 203
      docs/refman/loaderyaml.py
  7. 68
      docs/refman/main.py
  8. 113
      docs/refman/model.py
  9. 4
      run_mypy.py

@ -0,0 +1,27 @@
#!/usr/bin/env python3
# Copyright 2021 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Hack to make relative imports to mlog possible
from pathlib import Path
import sys
root = Path(__file__).absolute().parents[1]
sys.path.insert(0, str(root))
# Now run the actual code
from refman.main import main
if __name__ == '__main__':
raise SystemExit(main())

@ -0,0 +1,67 @@
# Copyright 2021 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from abc import ABCMeta, abstractmethod
import typing as T
from .model import ReferenceManual, Function, Object, ObjectType, NamedObject
_N = T.TypeVar('_N', bound=NamedObject)
class GeneratorBase(metaclass=ABCMeta):
def __init__(self, manual: ReferenceManual) -> None:
self.manual = manual
@abstractmethod
def generate(self) -> None:
pass
@staticmethod
def brief(raw: _N) -> str:
desc_lines = raw.description.split('\n')
brief = desc_lines[0]
if '.' in brief and '[[' not in brief:
brief = brief[:brief.index('.')]
return brief.strip()
@staticmethod
def sorted_and_filtered(raw: T.List[_N]) -> T.List[_N]:
return sorted([x for x in raw if not x.hidden], key=lambda x: x.name)
@property
def functions(self) -> T.List[Function]:
return GeneratorBase.sorted_and_filtered(self.manual.functions)
@property
def objects(self) -> T.List[Object]:
return GeneratorBase.sorted_and_filtered(self.manual.objects)
@property
def elementary(self) -> T.List[Object]:
return [x for x in self.objects if x.obj_type == ObjectType.ELEMENTARY]
@property
def builtins(self) -> T.List[Object]:
return [x for x in self.objects if x.obj_type == ObjectType.BUILTIN]
@property
def returned(self) -> T.List[Object]:
return [x for x in self.objects if x.obj_type == ObjectType.RETURNED and x.defined_by_module is None]
@property
def modules(self) -> T.List[Object]:
return [x for x in self.objects if x.obj_type == ObjectType.MODULE]
def extract_returned_by_module(self, module: Object) -> T.List[Object]:
return [x for x in self.objects if x.obj_type == ObjectType.RETURNED and x.defined_by_module is module]

@ -0,0 +1,88 @@
# Copyright 2021 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .generatorbase import GeneratorBase
from .model import ReferenceManual, Object, Function, DataTypeInfo, Type, ObjectType
from mesonbuild import mlog
import typing as T
def my_nested() -> T.ContextManager[None]:
prefix = '|' * len(mlog.log_depth)
return mlog.nested(prefix)
class GeneratorPrint(GeneratorBase):
def _types_to_string(self, typ: Type) -> str:
def _data_type_to_str(dt: DataTypeInfo) -> str:
if dt.holds:
return f'{dt.data_type.name}[{self._types_to_string(dt.holds)}]'
return dt.data_type.name
return ' | '.join([_data_type_to_str(x) for x in typ.resolved])
def _generate_function(self, func: Function) -> None:
mlog.log()
mlog.log('Function', mlog.bold(func.name))
with my_nested():
desc = func.description
if '\n' in desc:
desc = desc[:desc.index('\n')]
mlog.log('Description:', mlog.bold(desc))
mlog.log('Return type:', mlog.bold(self._types_to_string(func.returns)))
mlog.log('Pos args: ', mlog.bold(str([x.name for x in func.posargs])))
mlog.log('Opt args: ', mlog.bold(str([x.name for x in func.optargs])))
mlog.log('Varargs: ', mlog.bold(func.varargs.name if func.varargs is not None else 'null'))
mlog.log('Kwargs base:', mlog.bold(func.kwargs_inherit.name if func.kwargs_inherit else 'null'))
mlog.log('Kwargs: ', mlog.bold(str(list(func.kwargs.keys()))))
def _generate_object(self, obj: Object) -> None:
tags = []
tags += [{
ObjectType.ELEMENTARY: mlog.yellow('[elementary]'),
ObjectType.BUILTIN: mlog.green('[builtin]'),
ObjectType.MODULE: mlog.blue('[module]'),
ObjectType.RETURNED: mlog.cyan('[returned]'),
}[obj.obj_type]]
if obj.is_container:
tags += [mlog.red('[container]')]
mlog.log()
mlog.log('Object', mlog.bold(obj.name), *tags)
with my_nested():
desc = obj.description
if '\n' in desc:
desc = desc[:desc.index('\n')]
mlog.log('Description:', mlog.bold(desc))
mlog.log('Returned by:', mlog.bold(str([x.name for x in obj.returned_by])))
mlog.log('Methods:')
with my_nested():
for m in obj.methods:
self._generate_function(m)
def generate(self) -> None:
mlog.log('\n\n', mlog.bold('=== Functions ==='), '\n')
for f in self.functions:
self._generate_function(f)
mlog.log('\n\n', mlog.bold('=== Elementary ==='), '\n')
for obj in self.elementary:
self._generate_object(obj)
mlog.log('\n\n', mlog.bold('=== Builtins ==='), '\n')
for obj in self.builtins:
self._generate_object(obj)
mlog.log('\n\n', mlog.bold('=== Returned objects ==='), '\n')
for obj in self.returned:
self._generate_object(obj)
mlog.log('\n\n', mlog.bold('=== Modules ==='), '\n')
for obj in self.modules:
self._generate_object(obj)
for mod_obj in self.extract_returned_by_module(obj):
self._generate_object(mod_obj)

@ -0,0 +1,215 @@
# Copyright 2021 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from abc import ABCMeta, abstractmethod
from pathlib import Path
import re
import typing as T
from .model import (
NamedObject,
FetureCheck,
ArgBase,
DataTypeInfo,
Type,
Function,
Method,
Object,
ObjectType,
ReferenceManual,
)
from mesonbuild import mlog
class _Resolver:
def __init__(self) -> None:
self.type_map: T.Dict[str, Object] = {}
self.func_map: T.Dict[str, T.Union[Function, Method]] = {}
self.processed_funcs: T.Set[str] = set()
def _validate_named_object(self, obj: NamedObject) -> None:
name_regex = re.compile(r'[a-zA-Z0-9_]+')
obj.name = obj.name.strip()
obj.description = obj.description.strip()
assert obj.name and obj.description, 'Both name and description must be set'
assert obj.name.islower(), f'Object names must be lower case ({obj.name})'
assert name_regex.match(obj.name) or obj.name == '[index]', f'Invalid name {obj.name}'
def _validate_feature_check(self, obj: FetureCheck) -> None:
meson_version_reg = re.compile(r'[0-9]+\.[0-9]+\.[0-9]+')
obj.since = obj.since.strip()
obj.deprecated = obj.deprecated.strip()
if obj.since:
assert meson_version_reg.match(obj.since)
if obj.deprecated:
assert meson_version_reg.match(obj.deprecated)
def _resolve_type(self, raw: str) -> Type:
typ = Type(raw)
# We can't use `types = raw.split('|')`, because of `list[str | env]`
types: T.List[str] = ['']
stack = 0
for c in raw:
if stack == 0 and c == '|':
types += ['']
continue
if c == '[':
stack += 1
if c == ']':
stack -= 1
types[-1] += c
types = [x.strip() for x in types]
for t in types:
t = t.strip()
idx = t.find('[')
base_type = t
held_type = None
if idx > 0:
base_type = t[:idx]
held_type = self._resolve_type(t[idx+1:-1])
assert base_type in self.type_map, f'No known object {t}'
obj = self.type_map[base_type]
typ.resolved += [DataTypeInfo(obj, held_type)]
return typ
def _validate_func(self, func: T.Union[Function, Method]) -> None:
# Always run basic checks, since they also slightly post-process (strip) some strings
self._validate_named_object(func)
self._validate_feature_check(func)
func_id = f'{func.obj.name}.{func.name}' if isinstance(func, Method) else func.name
if func_id in self.processed_funcs:
return
func.returns = self._resolve_type(func.returns.raw)
all_args: T.List[ArgBase] = []
all_args += func.posargs
all_args += func.optargs
all_args += func.kwargs.values()
all_args += [func.varargs] if func.varargs else []
for arg in all_args:
arg.type = self._resolve_type(arg.type.raw)
# Handle returned_by
for obj in func.returns.resolved:
obj.data_type.returned_by += [func]
# Handle kwargs inehritance
for base_name in func.kwargs_inherit:
base_name = base_name.strip()
assert base_name in self.func_map, f'Unknown base function `{base_name}` for {func.name}'
base = self.func_map[base_name]
if base_name not in self.processed_funcs:
self._validate_func(base)
curr_keys = set(func.kwargs.keys())
base_keys = set(base.kwargs.keys())
# Calculate the missing kwargs from the current set
missing = {k: v for k, v in base.kwargs.items() if k in base_keys - curr_keys}
func.kwargs.update(missing)
# Handloe other args inheritance
_T = T.TypeVar('_T', bound=T.Union[ArgBase, T.List[ArgBase]])
def resolve_inherit(name: str, curr: _T, resolver: T.Callable[[Function], _T]) -> _T:
if name and not curr:
name = name.strip()
assert name in self.func_map, f'Unknown base function `{name}` for {func.name}'
if name not in self.processed_funcs:
self._validate_func(self.func_map[name])
ref_args = resolver(self.func_map[name])
assert ref_args is not None, f'Inherited function `{name}` does not have inherited args set'
return ref_args
return curr
func.posargs = resolve_inherit(func.posargs_inherit, func.posargs, lambda x: x.posargs)
func.optargs = resolve_inherit(func.optargs_inherit, func.optargs, lambda x: x.optargs)
func.varargs = resolve_inherit(func.varargs_inherit, func.varargs, lambda x: x.varargs)
self.processed_funcs.add(func_id)
def validate_and_resolve(self, manual: ReferenceManual) -> ReferenceManual:
mlog.log('Validating loaded manual...')
# build type map and func map for methods
for obj in manual.objects:
assert obj.name not in self.type_map, f'Duplicate object name {obj.name}'
self.type_map[obj.name] = obj
for m in obj.methods:
mid = f'{obj.name}.{m.name}'
assert mid not in self.type_map, f'Duplicate metod {mid}'
self.func_map[mid] = m
# Build func map for functions
for func in manual.functions:
assert func.name not in [*self.func_map.keys()], f'Duplicate function {func.name}'
self.func_map[func.name] = func
mlog.log('Validating functions...')
for func in manual.functions:
mlog.log(' -- validating', mlog.bold(func.name))
self._validate_func(func)
mlog.log('Validating objects...')
for obj in manual.objects:
mlog.log(' -- validating', mlog.bold(obj.name))
self._validate_named_object(obj)
self._validate_feature_check(obj)
# Resolve and validate inheritence
if obj.extends:
assert obj.extends in self.type_map, f'Unknown extends object {obj.extends} in {obj.name}'
obj.extends_obj = self.type_map[obj.extends]
obj.extends_obj.extended_by += [obj]
# Only returned objects can be associated with module
if obj.obj_type is not ObjectType.RETURNED:
assert obj.defined_by_module is None
for m in obj.methods:
assert m.obj is obj
self._validate_func(m)
# Resolve inherited methods
for obj in manual.objects:
inherited_methods = obj.inherited_methods
curr = obj.extends_obj
while curr is not None:
inherited_methods += curr.methods
curr = curr.extends_obj
return manual
class LoaderBase(metaclass=ABCMeta):
def __init__(self) -> None:
self._input_files: T.List[Path] = []
@property
def input_files(self) -> T.List[Path]:
return list(self._input_files)
def read_file(self, f: Path) -> str:
assert f.exists()
assert f.is_file()
self._input_files += [f.resolve()]
return f.read_text(encoding='utf-8')
@abstractmethod
def load_impl(self) -> ReferenceManual:
pass
def load(self) -> ReferenceManual:
self._input_files = [] # Reset input files
manual = self.load_impl()
resolver = _Resolver()
with mlog.nested():
return resolver.validate_and_resolve(manual)

@ -0,0 +1,203 @@
# Copyright 2021 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .loaderbase import LoaderBase
from .model import (
Type,
PosArg,
VarArgs,
Kwarg,
Function,
Method,
ObjectType,
Object,
ReferenceManual,
)
from mesonbuild import mlog
from mesonbuild import mesonlib
from strictyaml import Map, MapPattern, Optional, Str, Seq, Int, Bool, load, EmptyList, OrValidator
from pathlib import Path
import typing as T
d_named_object = {
'name': Str(),
'description': Str(),
}
d_feture_check = {
Optional('since', default=''): Str(),
Optional('deprecated', default=''): Str(),
}
s_posarg = Map({
**d_feture_check,
'description': Str(),
'type': Str(),
Optional('default', default=''): Str(),
})
s_varargs = Map({
**d_named_object, **d_feture_check,
'type': Str(),
Optional('min_varargs', default=-1): Int(),
Optional('max_varargs', default=-1): Int(),
})
s_kwarg = Map({
**d_feture_check,
'type': Str(),
'description': Str(),
Optional('required', default=False): Bool(),
Optional('default', default=''): Str(),
})
s_function = Map({
**d_named_object, **d_feture_check,
'returns': Str(),
Optional('notes', default=[]): OrValidator(Seq(Str()), EmptyList()),
Optional('warnings', default=[]): OrValidator(Seq(Str()), EmptyList()),
Optional('example', default=''): Str(),
Optional('posargs'): MapPattern(Str(), s_posarg),
Optional('optargs'): MapPattern(Str(), s_posarg),
Optional('varargs'): s_varargs,
Optional('posargs_inherit', default=''): Str(),
Optional('optargs_inherit', default=''): Str(),
Optional('varargs_inherit', default=''): Str(),
Optional('kwargs'): MapPattern(Str(), s_kwarg),
Optional('kwargs_inherit', default=[]): OrValidator(OrValidator(Seq(Str()), EmptyList()), Str()),
})
s_object = Map({
**d_named_object, **d_feture_check,
'long_name': Str(),
Optional('extends', default=''): Str(),
Optional('notes', default=[]): OrValidator(Seq(Str()), EmptyList()),
Optional('warnings', default=[]): OrValidator(Seq(Str()), EmptyList()),
Optional('example', default=''): Str(),
Optional('methods'): Seq(s_function),
Optional('is_container', default=False): Bool()
})
class LoaderYAML(LoaderBase):
def __init__(self, yaml_dir: Path) -> None:
super().__init__()
self.yaml_dir = yaml_dir
self.func_dir = self.yaml_dir / 'functions'
self.elem_dir = self.yaml_dir / 'elementary'
self.objs_dir = self.yaml_dir / 'objects'
self.builtin_dir = self.yaml_dir / 'builtins'
self.modules_dir = self.yaml_dir / 'modules'
def _process_function_base(self, raw: T.OrderedDict, obj: T.Optional[Object] = None) -> Function:
# Handle arguments
posargs = raw.pop('posargs', {})
optargs = raw.pop('optargs', {})
varargs = raw.pop('varargs', None)
kwargs = raw.pop('kwargs', {})
# Fix kwargs_inherit
if isinstance(raw['kwargs_inherit'], str):
raw['kwargs_inherit'] = [raw['kwargs_inherit']]
# Parse args
posargs_mapped: T.List[PosArg] = []
optargs_mapped: T.List[PosArg] = []
varargs_mapped: T.Optional[VarArgs] = None
kwargs_mapped: T.Dict[str, Kwarg] = {}
for k, v in posargs.items():
v['type'] = Type(v['type'])
posargs_mapped += [PosArg(name=k, **v)]
for k, v in optargs.items():
v['type'] = Type(v['type'])
optargs_mapped += [PosArg(name=k, **v)]
for k, v in kwargs.items():
v['type'] = Type(v['type'])
kwargs_mapped[k] = Kwarg(name=k, **v)
if varargs is not None:
varargs['type'] = Type(varargs['type'])
varargs_mapped = VarArgs(**varargs)
raw['returns'] = Type(raw['returns'])
# Build function object
if obj is not None:
return Method(
posargs=posargs_mapped,
optargs=optargs_mapped,
varargs=varargs_mapped,
kwargs=kwargs_mapped,
obj=obj,
**raw,
)
return Function(
posargs=posargs_mapped,
optargs=optargs_mapped,
varargs=varargs_mapped,
kwargs=kwargs_mapped,
**raw,
)
def _load_function(self, path: Path, obj: T.Optional[Object] = None) -> Function:
path_label = path.relative_to(self.yaml_dir).as_posix()
mlog.log('Loading', mlog.bold(path_label))
raw = load(self.read_file(path), s_function, label=path_label).data
return self._process_function_base(raw)
def _load_object(self, obj_type: ObjectType, path: Path) -> Object:
path_label = path.relative_to(self.yaml_dir).as_posix()
mlog.log(f'Loading', mlog.bold(path_label))
raw = load(self.read_file(path), s_object, label=path_label).data
def as_methods(mlist: T.List[Function]) -> T.List[Method]:
res: T.List[Method] = []
for i in mlist:
assert isinstance(i, Method)
res += [i]
return res
methods = raw.pop('methods', [])
obj = Object(methods=[], obj_type=obj_type, **raw)
obj.methods = as_methods([self._process_function_base(x, obj) for x in methods])
return obj
def _load_module(self, path: Path) -> T.List[Object]:
assert path.is_dir()
module = self._load_object(ObjectType.MODULE, path / 'module.yaml')
objs = []
for p in path.iterdir():
if p.name == 'module.yaml':
continue
obj = self._load_object(ObjectType.RETURNED, p)
obj.defined_by_module = module
objs += [obj]
return [module, *objs]
def load_impl(self) -> ReferenceManual:
mlog.log('Loading YAML refererence manual')
with mlog.nested():
return ReferenceManual(
functions=[self._load_function(x) for x in self.func_dir.iterdir()],
objects=mesonlib.listify([
[self._load_object(ObjectType.ELEMENTARY, x) for x in self.elem_dir.iterdir()],
[self._load_object(ObjectType.RETURNED, x) for x in self.objs_dir.iterdir()],
[self._load_object(ObjectType.BUILTIN, x) for x in self.builtin_dir.iterdir()],
[self._load_module(x) for x in self.modules_dir.iterdir()]
], flatten=True)
)

@ -0,0 +1,68 @@
# Copyright 2021 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from pathlib import Path
import argparse
import typing as T
from mesonbuild import mlog
from .loaderbase import LoaderBase
from .loaderyaml import LoaderYAML
from .generatorbase import GeneratorBase
from .generatorprint import GeneratorPrint
meson_root = Path(__file__).absolute().parents[2]
def main() -> int:
parser = argparse.ArgumentParser(description='Meson reference manual generator')
parser.add_argument('-l', '--loader', type=str, default='yaml', choices=['yaml'], help='Information loader backend')
parser.add_argument('-g', '--generator', type=str, choices=['print'], required=True, help='Generator backend')
parser.add_argument('--depfile', type=Path, default=None, help='Set to generate a depfile')
parser.add_argument('--force-color', action='store_true', help='Force enable colors')
args = parser.parse_args()
if args.force_color:
mlog.colorize_console = lambda: True
loaders: T.Dict[str, T.Callable[[], LoaderBase]] = {
'yaml': lambda: LoaderYAML(meson_root / 'docs' / 'yaml'),
}
loader = loaders[args.loader]()
refMan = loader.load()
generators: T.Dict[str, T.Callable[[], GeneratorBase]] = {
'print': lambda: GeneratorPrint(refMan),
}
generator = generators[args.generator]()
# Generate the depfile if required
if args.depfile is not None:
assert isinstance(args.depfile, Path)
assert isinstance(args.out, Path)
# Also add all files of this package
script_files = list(Path(__file__).resolve().parent.glob('**/*.py'))
templates = list(Path(__file__).resolve().parent.glob('**/*.mustache'))
out_text = f'{args.out.resolve().as_posix()}: \\\n'
for input in loader.input_files + script_files + templates:
out_text += f' {input.resolve().as_posix():<93} \\\n'
args.depfile.write_text(out_text, encoding='utf-8')
generator.generate()
return 0

@ -0,0 +1,113 @@
# Copyright 2021 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from dataclasses import dataclass, field
from enum import Enum
import typing as T
# Utils
@dataclass
class NamedObject:
name: str
description: str
@property
def hidden(self) -> bool:
return self.name.startswith('_')
@dataclass
class FetureCheck:
since: str
deprecated: str
@dataclass
class DataTypeInfo:
data_type: 'Object'
holds: T.Optional['Type']
@dataclass
class Type:
raw: str
resolved: T.List[DataTypeInfo] = field(init=False, default_factory=list)
# Arguments
@dataclass
class ArgBase(NamedObject):
type: Type
@dataclass
class PosArg(ArgBase, FetureCheck):
default: str
@dataclass
class VarArgs(ArgBase, FetureCheck):
min_varargs: int
max_varargs: int
@dataclass
class Kwarg(ArgBase, FetureCheck):
required: bool
default: str
# Function
@dataclass
class Function(NamedObject, FetureCheck):
notes: T.List[str]
warnings: T.List[str]
returns: Type
example: str
posargs: T.List[PosArg]
optargs: T.List[PosArg]
varargs: T.Optional[VarArgs]
kwargs: T.Dict[str, Kwarg]
posargs_inherit: str
optargs_inherit: str
varargs_inherit: str
kwargs_inherit: T.List[str]
@dataclass
class Method(Function):
obj: 'Object'
# Types and objects
class ObjectType(Enum):
ELEMENTARY = 0
BUILTIN = 1
MODULE = 2
RETURNED = 3
@dataclass
class Object(NamedObject, FetureCheck):
notes: T.List[str]
warnings: T.List[str]
long_name: str
example: str
obj_type: ObjectType
methods: T.List[Method]
is_container: bool
extends: str
extends_obj: T.Optional['Object'] = None
defined_by_module: T.Optional['Object'] = None
returned_by: T.List[T.Union[Function, Method]] = field(default_factory=list)
extended_by: T.List['Object'] = field(default_factory=list)
inherited_methods: T.List[Method] = field(default_factory=list)
# ROOT
@dataclass
class ReferenceManual:
functions: T.List[Function]
objects: T.List[Object]

@ -53,7 +53,9 @@ modules = [
'run_mypy.py',
'run_project_tests.py',
'run_single_test.py',
'tools'
'tools',
'docs/genrefman.py',
'docs/refman',
]
if os.name == 'posix':

Loading…
Cancel
Save