| # 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) |
| ) |