The Meson Build System
http://mesonbuild.com/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
6.9 KiB
203 lines
6.9 KiB
# 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) |
|
)
|
|
|