diff options
author | Daniel Mensinger <daniel@mensinger-ka.de> | 2021-06-25 19:48:43 +0200 |
---|---|---|
committer | Daniel Mensinger <daniel@mensinger-ka.de> | 2021-10-03 11:46:34 +0200 |
commit | ad65a699f93a7659739287882ca27c58c564670b (patch) | |
tree | 956660da72b5322e1860c27f159da5d0463d5aca /docs/refman/loaderyaml.py | |
parent | 3feaea6b29197cd224fbce0ac65fd43d08c3beac (diff) | |
download | meson-ad65a699f93a7659739287882ca27c58c564670b.zip meson-ad65a699f93a7659739287882ca27c58c564670b.tar.gz meson-ad65a699f93a7659739287882ca27c58c564670b.tar.bz2 |
docs: Initial reference manual generator
Diffstat (limited to 'docs/refman/loaderyaml.py')
-rw-r--r-- | docs/refman/loaderyaml.py | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/docs/refman/loaderyaml.py b/docs/refman/loaderyaml.py new file mode 100644 index 0000000..1f80185 --- /dev/null +++ b/docs/refman/loaderyaml.py @@ -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) + ) |