aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2022-03-09 12:35:39 -0800
committerEli Schwartz <eschwartz93@gmail.com>2022-08-18 21:57:36 -0400
commite84f293f672a372d2434d0ce4fa39d3f902b6ce8 (patch)
tree4df98f7d45469ef9fc12f92ef640f9de52bfece7
parentddb95b0ed8c09808388c94da4f4f47f9dc0633af (diff)
downloadmeson-e84f293f672a372d2434d0ce4fa39d3f902b6ce8.zip
meson-e84f293f672a372d2434d0ce4fa39d3f902b6ce8.tar.gz
meson-e84f293f672a372d2434d0ce4fa39d3f902b6ce8.tar.bz2
modules/pkgconfig: Use typed_kwargs
-rw-r--r--mesonbuild/interpreter/interpreter.py25
-rw-r--r--mesonbuild/modules/pkgconfig.py156
-rw-r--r--test cases/failing/46 pkgconfig variables zero length/test.json2
-rw-r--r--test cases/failing/47 pkgconfig variables zero length value/test.json2
-rw-r--r--test cases/failing/48 pkgconfig variables not key value/test.json2
5 files changed, 101 insertions, 86 deletions
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index b904055..9873888 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -85,8 +85,6 @@ from .type_checking import (
VARIABLES_KW,
NoneType,
in_set_validator,
- variables_validator,
- variables_convertor,
env_convertor_with_method
)
from . import primitives as P_OBJ
@@ -672,29 +670,6 @@ class Interpreter(InterpreterBase, HoldableObject):
def func_files(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[mesonlib.File]:
return self.source_strings_to_files(args[0])
- # Used by pkgconfig.generate()
- def extract_variables(self, kwargs: T.Dict[str, T.Union[T.Dict[str, str], T.List[str], str]],
- argname: str = 'variables', list_new: bool = False,
- dict_new: bool = False) -> T.Dict[str, str]:
- variables = kwargs.get(argname, {})
- if isinstance(variables, dict):
- if dict_new and variables:
- FeatureNew.single_use(f'{argname} as dictionary', '0.56.0', self.subproject, location=self.current_node)
- else:
- variables = mesonlib.stringlistify(variables)
- if list_new:
- FeatureNew.single_use(f'{argname} as list of strings', '0.56.0', self.subproject, location=self.current_node)
-
- invalid_msg = variables_validator(variables)
- if invalid_msg is not None:
- raise InterpreterException(invalid_msg)
-
- variables = variables_convertor(variables)
- for k, v in variables.items():
- if not isinstance(v, str):
- raise InterpreterException('variables values must be strings.')
-
- return variables
@noPosargs
@typed_kwargs(
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index 321fa97..ce0fa53 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -25,15 +25,59 @@ from .. import mesonlib
from .. import mlog
from ..coredata import BUILTIN_DIR_OPTIONS
from ..dependencies import ThreadDependency
-from ..interpreterbase import permittedKwargs, FeatureNew, FeatureDeprecated, FeatureNewKwargs
-from ..interpreterbase.decorators import typed_pos_args
+from ..interpreter.type_checking import D_MODULE_VERSIONS_KW, INSTALL_DIR_KW, VARIABLES_KW, NoneType
+from ..interpreterbase import FeatureNew, FeatureDeprecated
+from ..interpreterbase.decorators import ContainerTypeInfo, KwargInfo, typed_kwargs, typed_pos_args
if T.TYPE_CHECKING:
+ from typing_extensions import TypedDict
+
from . import ModuleState
from ..interpreter import Interpreter
+ ANY_DEP = T.Union[dependencies.Dependency, build.BuildTargetTypes, str]
+ LIBS = T.Union[build.LibTypes, str]
+
+ class GenerateKw(TypedDict):
+
+ version: T.Optional[str]
+ name: T.Optional[str]
+ filebase: T.Optional[str]
+ description: T.Optional[str]
+ url: str
+ subdirs: T.List[str]
+ conflicts: T.List[str]
+ dataonly: bool
+ libraries: T.List[ANY_DEP]
+ libraries_private: T.List[ANY_DEP]
+ requires: T.List[T.Union[str, build.StaticLibrary, build.SharedLibrary, dependencies.Dependency]]
+ requires_private: T.List[T.Union[str, build.StaticLibrary, build.SharedLibrary, dependencies.Dependency]]
+ install_dir: T.Optional[str]
+ d_module_versions: T.List[T.Union[str, int]]
+ extra_cflags: T.List[str]
+ variables: T.Dict[str, str]
+ uninstalled_variables: T.Dict[str, str]
+ unescaped_variables: T.Dict[str, str]
+ unescaped_uninstalled_variables: T.Dict[str, str]
+
already_warned_objs = set()
+_PKG_LIBRARIES: KwargInfo[T.List[T.Union[str, dependencies.Dependency, build.SharedLibrary, build.StaticLibrary, build.CustomTarget, build.CustomTargetIndex]]] = KwargInfo(
+ 'libraries',
+ ContainerTypeInfo(list, (str, dependencies.Dependency,
+ build.SharedLibrary, build.StaticLibrary,
+ build.CustomTarget, build.CustomTargetIndex)),
+ default=[],
+ listify=True,
+)
+
+_PKG_REQUIRES: KwargInfo[T.List[T.Union[str, build.SharedLibrary, build.StaticLibrary, dependencies.Dependency]]] = KwargInfo(
+ 'requires',
+ ContainerTypeInfo(list, (str, build.SharedLibrary, build.StaticLibrary, dependencies.Dependency)),
+ default=[],
+ listify=True,
+)
+
class DependenciesHelper:
def __init__(self, state: ModuleState, name: str) -> None:
self.state = state
@@ -502,23 +546,37 @@ class PkgConfigModule(ExtensionModule):
if cflags and not dataonly:
ofile.write('Cflags: {}\n'.format(' '.join(cflags)))
- @FeatureNewKwargs('pkgconfig.generate', '0.59.0', ['unescaped_variables', 'unescaped_uninstalled_variables'])
- @FeatureNewKwargs('pkgconfig.generate', '0.54.0', ['uninstalled_variables'])
- @FeatureNewKwargs('pkgconfig.generate', '0.42.0', ['extra_cflags'])
- @FeatureNewKwargs('pkgconfig.generate', '0.41.0', ['variables'])
- @FeatureNewKwargs('pkgconfig.generate', '0.54.0', ['dataonly'])
- @permittedKwargs({'libraries', 'version', 'name', 'description', 'filebase',
- 'subdirs', 'requires', 'requires_private', 'libraries_private',
- 'install_dir', 'extra_cflags', 'variables', 'url', 'd_module_versions',
- 'dataonly', 'conflicts', 'uninstalled_variables',
- 'unescaped_variables', 'unescaped_uninstalled_variables'})
@typed_pos_args('pkgconfig.generate', optargs=[(build.SharedLibrary, build.StaticLibrary)])
- def generate(self, state: ModuleState, args: T.Tuple[T.Optional[T.Union[build.SharedLibrary, build.StaticLibrary]]], kwargs):
+ @typed_kwargs(
+ 'pkgconfig.generate',
+ D_MODULE_VERSIONS_KW.evolve(since='0.43.0'),
+ INSTALL_DIR_KW,
+ KwargInfo('conflicts', ContainerTypeInfo(list, str), default=[], listify=True),
+ KwargInfo('dataonly', bool, default=False, since='0.54.0'),
+ KwargInfo('description', (str, NoneType)),
+ KwargInfo('extra_cflags', ContainerTypeInfo(list, str), default=[], listify=True, since='0.42.0'),
+ KwargInfo('filebase', (str, NoneType), validator=lambda x: 'must not be an empty string' if x == '' else None),
+ KwargInfo('name', (str, NoneType), validator=lambda x: 'must not be an empty string' if x == '' else None),
+ KwargInfo('subdirs', ContainerTypeInfo(list, str), default=[], listify=True),
+ KwargInfo('url', str, default=''),
+ KwargInfo('version', (str, NoneType)),
+ VARIABLES_KW.evolve(name="unescaped_uninstalled_variables", since='0.59.0'),
+ VARIABLES_KW.evolve(name="unescaped_variables", since='0.59.0'),
+ VARIABLES_KW.evolve(name="uninstalled_variables", since='0.54.0', since_values={dict: '0.56.0'}),
+ VARIABLES_KW.evolve(since='0.41.0', since_values={dict: '0.56.0'}),
+ _PKG_LIBRARIES,
+ _PKG_LIBRARIES.evolve(name='libraries_private'),
+ _PKG_REQUIRES,
+ _PKG_REQUIRES.evolve(name='requires_private'),
+ )
+ def generate(self, state: ModuleState,
+ args: T.Tuple[T.Optional[T.Union[build.SharedLibrary, build.StaticLibrary]]],
+ kwargs: GenerateKw) -> ModuleReturnValue:
default_version = state.project_version
- default_install_dir = None
- default_description = None
- default_name = None
- mainlib = None
+ default_install_dir: T.Optional[str] = None
+ default_description: T.Optional[str] = None
+ default_name: T.Optional[str] = None
+ mainlib: T.Optional[T.Union[build.SharedLibrary, build.StaticLibrary]] = None
default_subdirs = ['.']
if args[0]:
FeatureNew.single_use('pkgconfig.generate optional positional argument', '0.46.0', state.subproject)
@@ -528,52 +586,40 @@ class PkgConfigModule(ExtensionModule):
install_dir = mainlib.get_custom_install_dir()
if install_dir and isinstance(install_dir[0], str):
default_install_dir = os.path.join(install_dir[0], 'pkgconfig')
- elif 'version' not in kwargs:
+ elif kwargs['version'] is None:
FeatureNew.single_use('pkgconfig.generate implicit version keyword', '0.46.0', state.subproject)
- dataonly = kwargs.get('dataonly', False)
- if not isinstance(dataonly, bool):
- raise mesonlib.MesonException('dataonly must be boolean.')
+ dataonly = kwargs['dataonly']
if dataonly:
default_subdirs = []
blocked_vars = ['libraries', 'libraries_private', 'requires_private', 'extra_cflags', 'subdirs']
- if any(k in kwargs for k in blocked_vars):
+ if any(kwargs[k] for k in blocked_vars):
raise mesonlib.MesonException(f'Cannot combine dataonly with any of {blocked_vars}')
default_install_dir = os.path.join(state.environment.get_datadir(), 'pkgconfig')
- subdirs = mesonlib.stringlistify(kwargs.get('subdirs', default_subdirs))
- version = kwargs.get('version', default_version)
- if not isinstance(version, str):
- raise mesonlib.MesonException('Version must be specified.')
- name = kwargs.get('name', default_name)
- if not isinstance(name, str):
- raise mesonlib.MesonException('Name not specified.')
- filebase = kwargs.get('filebase', name)
- if not isinstance(filebase, str):
- raise mesonlib.MesonException('Filebase must be a string.')
- description = kwargs.get('description', default_description)
- if not isinstance(description, str):
- raise mesonlib.MesonException('Description is not a string.')
- url = kwargs.get('url', '')
- if not isinstance(url, str):
- raise mesonlib.MesonException('URL is not a string.')
- conflicts = mesonlib.stringlistify(kwargs.get('conflicts', []))
+ subdirs = kwargs['subdirs'] or default_subdirs
+ version = kwargs['version'] if kwargs['version'] is not None else default_version
+ name = kwargs['name'] if kwargs['name'] is not None else default_name
+ filebase = kwargs['filebase'] if kwargs['filebase'] is not None else name
+ description = kwargs['description'] if kwargs['description'] is not None else default_description
+ url = kwargs['url']
+ conflicts = kwargs['conflicts']
# Prepend the main library to public libraries list. This is required
# so dep.add_pub_libs() can handle dependency ordering correctly and put
# extra libraries after the main library.
- libraries = mesonlib.extract_as_list(kwargs, 'libraries')
+ libraries = kwargs['libraries'].copy()
if mainlib:
- libraries = [mainlib] + libraries
+ libraries.insert(0, mainlib)
deps = DependenciesHelper(state, filebase)
deps.add_pub_libs(libraries)
- deps.add_priv_libs(kwargs.get('libraries_private', []))
- deps.add_pub_reqs(kwargs.get('requires', []))
- deps.add_priv_reqs(kwargs.get('requires_private', []))
- deps.add_cflags(kwargs.get('extra_cflags', []))
+ deps.add_priv_libs(kwargs['libraries_private'])
+ deps.add_pub_reqs(kwargs['requires'])
+ deps.add_priv_reqs(kwargs['requires_private'])
+ deps.add_cflags(kwargs['extra_cflags'])
- dversions = kwargs.get('d_module_versions', None)
+ dversions = kwargs['d_module_versions']
if dversions:
compiler = state.environment.coredata.compilers.host.get('d')
if compiler:
@@ -581,7 +627,7 @@ class PkgConfigModule(ExtensionModule):
deps.remove_dups()
- def parse_variable_list(vardict):
+ def parse_variable_list(vardict: T.Dict[str, str]) -> T.List[T.Tuple[str, str]]:
reserved = ['prefix', 'libdir', 'includedir']
variables = []
for name, value in vardict.items():
@@ -590,13 +636,11 @@ class PkgConfigModule(ExtensionModule):
variables.append((name, value))
return variables
- variables = self.interpreter.extract_variables(kwargs, dict_new=True)
- variables = parse_variable_list(variables)
- unescaped_variables = self.interpreter.extract_variables(kwargs, argname='unescaped_variables')
- unescaped_variables = parse_variable_list(unescaped_variables)
+ variables = parse_variable_list(kwargs['variables'])
+ unescaped_variables = parse_variable_list(kwargs['unescaped_variables'])
pcfile = filebase + '.pc'
- pkgroot = pkgroot_name = kwargs.get('install_dir', default_install_dir)
+ pkgroot = pkgroot_name = kwargs['install_dir'] or default_install_dir
if pkgroot is None:
if mesonlib.is_freebsd():
pkgroot = os.path.join(state.environment.coredata.get_option(mesonlib.OptionKey('prefix')), 'libdata', 'pkgconfig')
@@ -604,18 +648,14 @@ class PkgConfigModule(ExtensionModule):
else:
pkgroot = os.path.join(state.environment.coredata.get_option(mesonlib.OptionKey('libdir')), 'pkgconfig')
pkgroot_name = os.path.join('{libdir}', 'pkgconfig')
- if not isinstance(pkgroot, str):
- raise mesonlib.MesonException('Install_dir must be a string.')
relocatable = state.get_option('relocatable', module='pkgconfig')
self._generate_pkgconfig_file(state, deps, subdirs, name, description, url,
version, pcfile, conflicts, variables,
unescaped_variables, False, dataonly,
pkgroot=pkgroot if relocatable else None)
res = build.Data([mesonlib.File(True, state.environment.get_scratch_dir(), pcfile)], pkgroot, pkgroot_name, None, state.subproject, install_tag='devel')
- variables = self.interpreter.extract_variables(kwargs, argname='uninstalled_variables', dict_new=True)
- variables = parse_variable_list(variables)
- unescaped_variables = self.interpreter.extract_variables(kwargs, argname='unescaped_uninstalled_variables')
- unescaped_variables = parse_variable_list(unescaped_variables)
+ variables = parse_variable_list(kwargs['uninstalled_variables'])
+ unescaped_variables = parse_variable_list(kwargs['unescaped_uninstalled_variables'])
pcfile = filebase + '-uninstalled.pc'
self._generate_pkgconfig_file(state, deps, subdirs, name, description, url,
diff --git a/test cases/failing/46 pkgconfig variables zero length/test.json b/test cases/failing/46 pkgconfig variables zero length/test.json
index 91c6ea1..b174065 100644
--- a/test cases/failing/46 pkgconfig variables zero length/test.json
+++ b/test cases/failing/46 pkgconfig variables zero length/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/46 pkgconfig variables zero length/meson.build:8:5: ERROR: empty variable name"
+ "line": "test cases/failing/46 pkgconfig variables zero length/meson.build:8:5: ERROR: pkgconfig.generate keyword argument \"variables\" empty variable name"
}
]
}
diff --git a/test cases/failing/47 pkgconfig variables zero length value/test.json b/test cases/failing/47 pkgconfig variables zero length value/test.json
index 29c0541..0be5725 100644
--- a/test cases/failing/47 pkgconfig variables zero length value/test.json
+++ b/test cases/failing/47 pkgconfig variables zero length value/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/47 pkgconfig variables zero length value/meson.build:8:5: ERROR: empty variable value"
+ "line": "test cases/failing/47 pkgconfig variables zero length value/meson.build:8:5: ERROR: pkgconfig.generate keyword argument \"variables\" empty variable value"
}
]
}
diff --git a/test cases/failing/48 pkgconfig variables not key value/test.json b/test cases/failing/48 pkgconfig variables not key value/test.json
index b32e886..96422a9 100644
--- a/test cases/failing/48 pkgconfig variables not key value/test.json
+++ b/test cases/failing/48 pkgconfig variables not key value/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/48 pkgconfig variables not key value/meson.build:8:5: ERROR: variable 'this_should_be_key_value' must have a value separated by equals sign."
+ "line": "test cases/failing/48 pkgconfig variables not key value/meson.build:8:5: ERROR: pkgconfig.generate keyword argument \"variables\" variable 'this_should_be_key_value' must have a value separated by equals sign."
}
]
}