modules: use module level information about new and deprecation

Instead of using FeatureNew/FeatureDeprecated in the module.

The goal here is to be able to handle information about modules in a
single place, instead of having to handle it separately. Each module
simply defines some metadata, and then the interpreter handles the rest.
pull/10702/head
Dylan Baker 3 years ago committed by Eli Schwartz
parent 2801ead6d3
commit 6843f56f6b
  1. 15
      mesonbuild/interpreter/interpreter.py
  2. 18
      mesonbuild/modules/__init__.py
  3. 5
      mesonbuild/modules/cmake.py
  4. 7
      mesonbuild/modules/dlang.py
  5. 5
      mesonbuild/modules/fs.py
  6. 5
      mesonbuild/modules/gnome.py
  7. 9
      mesonbuild/modules/hotdoc.py
  8. 5
      mesonbuild/modules/i18n.py
  9. 6
      mesonbuild/modules/java.py
  10. 7
      mesonbuild/modules/keyval.py
  11. 5
      mesonbuild/modules/modtest.py
  12. 5
      mesonbuild/modules/pkgconfig.py
  13. 5
      mesonbuild/modules/python.py
  14. 9
      mesonbuild/modules/python3.py
  15. 3
      mesonbuild/modules/qt4.py
  16. 3
      mesonbuild/modules/qt5.py
  17. 5
      mesonbuild/modules/qt6.py
  18. 6
      mesonbuild/modules/sourceset.py
  19. 7
      mesonbuild/modules/unstable_cuda.py
  20. 6
      mesonbuild/modules/unstable_external_project.py
  21. 6
      mesonbuild/modules/unstable_icestorm.py
  22. 7
      mesonbuild/modules/unstable_rust.py
  23. 7
      mesonbuild/modules/unstable_simd.py
  24. 7
      mesonbuild/modules/unstable_wayland.py
  25. 5
      mesonbuild/modules/windows.py
  26. 4
      test cases/common/253 module warnings/meson.build
  27. 10
      test cases/common/253 module warnings/test.json

@ -599,7 +599,7 @@ class Interpreter(InterpreterBase, HoldableObject):
dep = df.lookup(kwargs, force_fallback=True)
self.build.stdlibs[for_machine][l] = dep
def _import_module(self, modname: str, required: bool) -> NewExtensionModule:
def _import_module(self, modname: str, required: bool, node: mparser.BaseNode) -> NewExtensionModule:
if modname in self.modules:
return self.modules[modname]
try:
@ -607,11 +607,15 @@ class Interpreter(InterpreterBase, HoldableObject):
except ImportError:
if required:
raise InvalidArguments(f'Module "{modname}" does not exist')
ext_module = NotFoundExtensionModule()
ext_module = NotFoundExtensionModule(modname)
else:
ext_module = module.initialize(self)
assert isinstance(ext_module, (ExtensionModule, NewExtensionModule))
self.build.modules.append(modname)
if ext_module.INFO.added:
FeatureNew.single_use(f'module {ext_module.INFO.name}', ext_module.INFO.added, self.subproject, location=node)
if ext_module.INFO.deprecated:
FeatureDeprecated.single_use(f'module {ext_module.INFO.name}', ext_module.INFO.deprecated, self.subproject, location=node)
self.modules[modname] = ext_module
return ext_module
@ -627,20 +631,19 @@ class Interpreter(InterpreterBase, HoldableObject):
modname = args[0]
disabled, required, _ = extract_required_kwarg(kwargs, self.subproject)
if disabled:
return NotFoundExtensionModule()
return NotFoundExtensionModule(modname)
if modname.startswith('unstable-'):
plainname = modname.split('-', 1)[1]
try:
# check if stable module exists
mod = self._import_module(plainname, required)
# XXX: this is actually not helpful, since it doesn't do a version check
mod = self._import_module(plainname, required, node)
mlog.warning(f'Module {modname} is now stable, please use the {plainname} module instead.')
return mod
except InvalidArguments:
mlog.warning(f'Module {modname} has no backwards or forwards compatibility and might not exist in future releases.', location=node)
modname = 'unstable_' + plainname
return self._import_module(modname, required)
return self._import_module(modname, required, node)
@typed_pos_args('files', varargs=str)
@noKwargs

@ -15,6 +15,7 @@
# This file contains the base representation for import('modname')
from __future__ import annotations
import dataclasses
import typing as T
from .. import mesonlib
@ -163,6 +164,17 @@ class ModuleObject(HoldableObject):
class MutableModuleObject(ModuleObject):
pass
@dataclasses.dataclass
class ModuleInfo:
"""Metadata about a Module."""
name: str
added: T.Optional[str] = None
deprecated: T.Optional[str] = None
class NewExtensionModule(ModuleObject):
"""Class for modern modules
@ -170,6 +182,8 @@ class NewExtensionModule(ModuleObject):
provides the found method.
"""
INFO: ModuleInfo
def __init__(self) -> None:
super().__init__()
self.methods.update({
@ -203,6 +217,10 @@ class NotFoundExtensionModule(NewExtensionModule):
provides the found method.
"""
def __init__(self, name: str) -> None:
super().__init__()
self.INFO = ModuleInfo(name)
@staticmethod
def found() -> bool:
return False

@ -18,7 +18,7 @@ import os, os.path, pathlib
import shutil
import typing as T
from . import ExtensionModule, ModuleReturnValue, ModuleObject
from . import ExtensionModule, ModuleReturnValue, ModuleObject, ModuleInfo
from .. import build, mesonlib, mlog, dependencies
from ..cmake import TargetOptions, cmake_defines_to_args
@ -247,7 +247,8 @@ class CmakeModule(ExtensionModule):
cmake_detected = False
cmake_root = None
@FeatureNew('CMake Module', '0.50.0')
INFO = ModuleInfo('cmake', '0.50.0')
def __init__(self, interpreter):
super().__init__(interpreter)
self.methods.update({

@ -18,17 +18,18 @@
import json
import os
from . import ExtensionModule
from . import ExtensionModule, ModuleInfo
from .. import dependencies
from .. import mlog
from ..interpreterbase import FeatureNew, typed_pos_args
from ..interpreterbase import typed_pos_args
from ..mesonlib import Popen_safe, MesonException
class DlangModule(ExtensionModule):
class_dubbin = None
init_dub = False
@FeatureNew('Dlang Module', '0.48.0')
INFO = ModuleInfo('dlang', '0.48.0')
def __init__(self, interpreter):
super().__init__(interpreter)
self.methods.update({

@ -18,7 +18,7 @@ import os
from pathlib import Path, PurePath, PureWindowsPath
from .. import mlog
from . import ExtensionModule
from . import ExtensionModule, ModuleInfo
from ..mesonlib import (
File,
MesonException,
@ -41,7 +41,8 @@ if T.TYPE_CHECKING:
class FSModule(ExtensionModule):
@FeatureNew('Fs Module', '0.53.0')
INFO = ModuleInfo('fs', '0.53.0')
def __init__(self, interpreter: 'Interpreter') -> None:
super().__init__(interpreter)
self.methods.update({

@ -24,7 +24,7 @@ import subprocess
import textwrap
import typing as T
from . import ExtensionModule
from . import ExtensionModule, ModuleInfo
from . import ModuleReturnValue
from .. import build
from .. import interpreter
@ -272,6 +272,9 @@ gresource_dep_needed_version = '>= 2.51.1'
native_glib_version: T.Optional[str] = None
class GnomeModule(ExtensionModule):
INFO = ModuleInfo('gnome')
def __init__(self, interpreter: 'Interpreter') -> None:
super().__init__(interpreter)
self.gir_dep: T.Optional[Dependency] = None

@ -20,10 +20,10 @@ from collections import OrderedDict
from mesonbuild import mesonlib
from mesonbuild import mlog, build
from mesonbuild.coredata import MesonException
from . import ModuleReturnValue
from . import ModuleReturnValue, ModuleInfo
from . import ExtensionModule
from ..dependencies import Dependency, InternalDependency
from ..interpreterbase import FeatureNew, InvalidArguments, noPosargs, noKwargs, typed_pos_args
from ..interpreterbase import InvalidArguments, noPosargs, noKwargs, typed_pos_args
from ..interpreter import CustomTargetHolder
from ..programs import ExternalProgram
@ -38,6 +38,7 @@ MIN_HOTDOC_VERSION = '0.8.100'
class HotdocTargetBuilder:
def __init__(self, name, state, hotdoc, interpreter, kwargs):
self.hotdoc = hotdoc
self.build_by_default = kwargs.pop('build_by_default', False)
@ -396,7 +397,9 @@ class HotdocTarget(build.CustomTarget):
class HotDocModule(ExtensionModule):
@FeatureNew('Hotdoc Module', '0.48.0')
INFO = ModuleInfo('hotdoc', '0.48.0')
def __init__(self, interpreter):
super().__init__(interpreter)
self.hotdoc = ExternalProgram('hotdoc')

@ -16,7 +16,7 @@ from __future__ import annotations
from os import path
import typing as T
from . import ExtensionModule, ModuleReturnValue
from . import ExtensionModule, ModuleReturnValue, ModuleInfo
from .. import build
from .. import mesonlib
from .. import mlog
@ -124,6 +124,9 @@ PRESET_ARGS = {
class I18nModule(ExtensionModule):
INFO = ModuleInfo('i18n')
def __init__(self, interpreter: 'Interpreter'):
super().__init__(interpreter)
self.methods.update({

@ -22,7 +22,7 @@ from mesonbuild.build import CustomTarget, CustomTargetIndex, GeneratedList, Tar
from mesonbuild.compilers import detect_compiler_for
from mesonbuild.interpreterbase.decorators import ContainerTypeInfo, FeatureDeprecated, FeatureNew, KwargInfo, typed_pos_args, typed_kwargs
from mesonbuild.mesonlib import version_compare, MachineChoice
from . import NewExtensionModule, ModuleReturnValue
from . import NewExtensionModule, ModuleReturnValue, ModuleInfo
if T.TYPE_CHECKING:
from . import ModuleState
@ -30,7 +30,9 @@ if T.TYPE_CHECKING:
from ..interpreter import Interpreter
class JavaModule(NewExtensionModule):
@FeatureNew('Java Module', '0.60.0')
INFO = ModuleInfo('java', '0.60.0')
def __init__(self, interpreter: Interpreter):
super().__init__()
self.methods.update({

@ -15,9 +15,9 @@
import os
import typing as T
from . import ExtensionModule
from . import ExtensionModule, ModuleInfo
from .. import mesonlib
from ..interpreterbase import FeatureNew, noKwargs, typed_pos_args
from ..interpreterbase import noKwargs, typed_pos_args
if T.TYPE_CHECKING:
from ..interpreter import Interpreter
@ -25,7 +25,8 @@ if T.TYPE_CHECKING:
class KeyvalModule(ExtensionModule):
@FeatureNew('Keyval Module', '0.55.0')
INFO = ModuleInfo('keyval', '0.55.0')
def __init__(self, interp: 'Interpreter'):
super().__init__(interp)
self.methods.update({

@ -15,7 +15,7 @@
from __future__ import annotations
import typing as T
from . import ExtensionModule
from . import ExtensionModule, ModuleInfo
from ..interpreterbase import noKwargs, noPosargs
if T.TYPE_CHECKING:
@ -25,6 +25,9 @@ if T.TYPE_CHECKING:
class TestModule(ExtensionModule):
INFO = ModuleInfo('modtest')
def __init__(self, interpreter: Interpreter) -> None:
super().__init__(interpreter)
self.methods.update({

@ -16,7 +16,7 @@ from pathlib import PurePath
import os
import typing as T
from . import ExtensionModule
from . import ExtensionModule, ModuleInfo
from . import ModuleReturnValue
from .. import build
from .. import dependencies
@ -276,6 +276,9 @@ class DependenciesHelper:
self.cflags = _fn(self.cflags)
class PkgConfigModule(ExtensionModule):
INFO = ModuleInfo('pkgconfig')
def __init__(self, interpreter):
super().__init__(interpreter)
self.methods.update({

@ -20,7 +20,7 @@ import os
import shutil
import typing as T
from . import ExtensionModule
from . import ExtensionModule, ModuleInfo
from .. import mesonlib
from .. import mlog
from ..coredata import UserFeatureOption
@ -663,7 +663,8 @@ class PythonInstallation(ExternalProgramHolder):
class PythonModule(ExtensionModule):
@FeatureNew('Python Module', '0.46.0')
INFO = ModuleInfo('python', '0.46.0')
def __init__(self, interpreter: 'Interpreter') -> None:
super().__init__(interpreter)
self.installations: T.Dict[str, ExternalProgram] = {}

@ -15,15 +15,16 @@
import sysconfig
from .. import mesonlib
from . import ExtensionModule
from ..interpreterbase import typed_pos_args, noPosargs, noKwargs, permittedKwargs, FeatureDeprecated, FeatureNew
from . import ExtensionModule, ModuleInfo
from ..interpreterbase import typed_pos_args, noPosargs, noKwargs, permittedKwargs
from ..build import known_shmod_kwargs
from ..programs import ExternalProgram
class Python3Module(ExtensionModule):
@FeatureNew('python3 module', '0.38.0')
@FeatureDeprecated('python3 module', '0.48.0')
INFO = ModuleInfo('python3', '0.38.0', deprecated='0.48.0')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.methods.update({

@ -13,10 +13,13 @@
# limitations under the License.
from .qt import QtBaseModule
from . import ModuleInfo
class Qt4Module(QtBaseModule):
INFO = ModuleInfo('qt4')
def __init__(self, interpreter):
QtBaseModule.__init__(self, interpreter, qt_version=4)

@ -13,10 +13,13 @@
# limitations under the License.
from .qt import QtBaseModule
from . import ModuleInfo
class Qt5Module(QtBaseModule):
INFO = ModuleInfo('qt5')
def __init__(self, interpreter):
QtBaseModule.__init__(self, interpreter, qt_version=5)

@ -13,12 +13,13 @@
# limitations under the License.
from .qt import QtBaseModule
from ..interpreterbase import FeatureNew
from . import ModuleInfo
class Qt6Module(QtBaseModule):
@FeatureNew('Qt6 Module', '0.57.0')
INFO = ModuleInfo('qt6', '0.57.0')
def __init__(self, interpreter):
QtBaseModule.__init__(self, interpreter, qt_version=6)

@ -15,7 +15,7 @@
from __future__ import annotations
import typing as T
from . import ExtensionModule, ModuleObject, MutableModuleObject
from . import ExtensionModule, ModuleObject, MutableModuleObject, ModuleInfo
from .. import build
from .. import dependencies
from .. import mesonlib
@ -289,7 +289,9 @@ class SourceFilesObject(ModuleObject):
return list(self.files.deps)
class SourceSetModule(ExtensionModule):
@FeatureNew('SourceSet module', '0.51.0')
INFO = ModuleInfo('sourceset', '0.51.0')
def __init__(self, interpreter: Interpreter):
super().__init__(interpreter)
self.methods.update({

@ -19,11 +19,11 @@ import re
from ..mesonlib import version_compare
from ..compilers import CudaCompiler
from . import NewExtensionModule
from . import NewExtensionModule, ModuleInfo
from ..interpreterbase import (
flatten, permittedKwargs, noKwargs,
InvalidArguments, FeatureNew
InvalidArguments
)
if T.TYPE_CHECKING:
@ -32,7 +32,8 @@ if T.TYPE_CHECKING:
class CudaModule(NewExtensionModule):
@FeatureNew('CUDA module', '0.50.0')
INFO = ModuleInfo('CUDA', '0.50.0')
def __init__(self, *args, **kwargs):
super().__init__()
self.methods.update({

@ -18,7 +18,7 @@ import shlex
import subprocess
import typing as T
from . import ExtensionModule, ModuleReturnValue, NewExtensionModule
from . import ExtensionModule, ModuleReturnValue, NewExtensionModule, ModuleInfo
from .. import mlog, build
from ..compilers.compilers import CFLAGS_MAPPING
from ..envconfig import ENV_VAR_PROG_MAP
@ -273,7 +273,9 @@ class ExternalProject(NewExtensionModule):
class ExternalProjectModule(ExtensionModule):
@FeatureNew('External build system Module', '0.56.0')
INFO = ModuleInfo('External build system', '0.56.0')
def __init__(self, interpreter: 'Interpreter'):
super().__init__(interpreter)
self.methods.update({'add_project': self.add_project,

@ -16,11 +16,10 @@ from __future__ import annotations
import itertools
import typing as T
from . import ExtensionModule, ModuleReturnValue
from . import ExtensionModule, ModuleReturnValue, ModuleInfo
from .. import build
from .. import mesonlib
from ..interpreter.type_checking import CT_INPUT_KW
from ..interpreterbase import FeatureNew
from ..interpreterbase.decorators import KwargInfo, typed_kwargs, typed_pos_args
if T.TYPE_CHECKING:
@ -37,7 +36,8 @@ if T.TYPE_CHECKING:
class IceStormModule(ExtensionModule):
@FeatureNew('FPGA/Icestorm Module', '0.45.0')
INFO = ModuleInfo('FPGA/Icestorm', '0.45.0')
def __init__(self, interpreter: Interpreter) -> None:
super().__init__(interpreter)
self.tools: T.Dict[str, ExternalProgram] = {}

@ -15,12 +15,12 @@
import os
import typing as T
from . import ExtensionModule, ModuleReturnValue
from . import ExtensionModule, ModuleReturnValue, ModuleInfo
from .. import mlog
from ..build import BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, IncludeDirs, CustomTarget, StructuredSources
from ..dependencies import Dependency, ExternalLibrary
from ..interpreter.interpreter import TEST_KWARGS, OUTPUT_KW
from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, FeatureNew, typed_kwargs, typed_pos_args, noPosargs
from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs
from ..mesonlib import File
if T.TYPE_CHECKING:
@ -50,7 +50,8 @@ class RustModule(ExtensionModule):
"""A module that holds helper functions for rust."""
@FeatureNew('rust module', '0.57.0')
INFO = ModuleInfo('rust', '0.57.0')
def __init__(self, interpreter: 'Interpreter') -> None:
super().__init__(interpreter)
self._bindgen_bin: T.Optional['ExternalProgram'] = None

@ -15,13 +15,12 @@
from .. import mesonlib, compilers, mlog
from .. import build
from . import ExtensionModule
from ..interpreterbase import FeatureNew
from . import ExtensionModule, ModuleInfo
class SimdModule(ExtensionModule):
@FeatureNew('SIMD module', '0.42.0')
INFO = ModuleInfo('SIMD', '0.42.0')
def __init__(self, interpreter):
super().__init__(interpreter)
# FIXME add Altivec and AVX512.

@ -16,10 +16,10 @@ from __future__ import annotations
import os
import typing as T
from . import ExtensionModule, ModuleReturnValue
from . import ExtensionModule, ModuleReturnValue, ModuleInfo
from ..build import CustomTarget
from ..interpreter.type_checking import NoneType, in_set_validator
from ..interpreterbase import FeatureNew, typed_pos_args, typed_kwargs, KwargInfo
from ..interpreterbase import typed_pos_args, typed_kwargs, KwargInfo
from ..mesonlib import File, MesonException
if T.TYPE_CHECKING:
@ -45,7 +45,8 @@ if T.TYPE_CHECKING:
class WaylandModule(ExtensionModule):
@FeatureNew('wayland module', '0.62.0')
INFO = ModuleInfo('wayland', '0.62.0')
def __init__(self, interpreter: Interpreter) -> None:
super().__init__(interpreter)

@ -18,7 +18,7 @@ import re
import typing as T
from . import ExtensionModule
from . import ExtensionModule, ModuleInfo
from . import ModuleReturnValue
from .. import mesonlib, build
from .. import mlog
@ -55,6 +55,9 @@ class ResourceCompilerType(enum.Enum):
wrc = 3
class WindowsModule(ExtensionModule):
INFO = ModuleInfo('windows')
def __init__(self, interpreter: 'Interpreter'):
super().__init__(interpreter)
self._rescomp: T.Optional[T.Tuple[ExternalProgram, ResourceCompilerType]] = None

@ -0,0 +1,4 @@
project('module warnings', meson_version : '>= 0.56')
import('python3') # deprecated module
import('java') # new module

@ -0,0 +1,10 @@
{
"stdout": [
{
"line": "test cases/common/253 module warnings/meson.build:3: WARNING: Project targets '>= 0.56' but uses feature deprecated since '0.48.0': module python3."
},
{
"line": "test cases/common/253 module warnings/meson.build:4: WARNING: Project targets '>= 0.56' but uses feature introduced in '0.60.0': module java."
}
]
}
Loading…
Cancel
Save