aboutsummaryrefslogtreecommitdiff
path: root/docs/refman/loaderyaml.py
diff options
context:
space:
mode:
authorDaniel Mensinger <daniel@mensinger-ka.de>2021-06-25 19:48:43 +0200
committerDaniel Mensinger <daniel@mensinger-ka.de>2021-10-03 11:46:34 +0200
commitad65a699f93a7659739287882ca27c58c564670b (patch)
tree956660da72b5322e1860c27f159da5d0463d5aca /docs/refman/loaderyaml.py
parent3feaea6b29197cd224fbce0ac65fd43d08c3beac (diff)
downloadmeson-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.py203
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)
+ )