summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2024-10-27 10:17:54 -0700
committerEli Schwartz <eschwartz93@gmail.com>2024-11-05 17:41:38 -0500
commit6eb1a2726e15d4301b000b177e72e75263bdd499 (patch)
tree4df1d919d3b3e0d99784ac13a1eca012038fee22
parent909b04d5b1072f0d6421dbd2d420fa879ab80b36 (diff)
downloadmeson-6eb1a2726e15d4301b000b177e72e75263bdd499.tar.gz
cargo: Warn when encountering unknown keys
Cargo sometimes adds new keys and Meson needs to gracefully handle those. Currently, an unknown key will trigger an uncaught Python exception, which is pretty much the worse case. With this change Meson will instead issue a warning much like the one for unknown cpu architectures. See #13826 for the motivation for this change
-rw-r--r--mesonbuild/cargo/interpreter.py53
-rw-r--r--test cases/rust/22 cargo subproject/subprojects/bar-0.1-rs/Cargo.toml1
-rw-r--r--test cases/rust/22 cargo subproject/test.json8
3 files changed, 58 insertions, 4 deletions
diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py
index 6c0921224..0528c4c90 100644
--- a/mesonbuild/cargo/interpreter.py
+++ b/mesonbuild/cargo/interpreter.py
@@ -28,13 +28,22 @@ from ..wrap.wrap import PackageDefinition
if T.TYPE_CHECKING:
from types import ModuleType
- from typing_extensions import Self
+ from typing_extensions import Protocol, Self
from . import manifest
from .. import mparser
from ..environment import Environment
from ..interpreterbase import SubProject
+ # Copied from typeshed. Blarg that they don't expose this
+ class DataclassInstance(Protocol):
+ __dataclass_fields__: T.ClassVar[dict[str, dataclasses.Field[T.Any]]]
+
+ _UnknownKeysT = T.TypeVar('_UnknownKeysT', manifest.FixedPackage,
+ manifest.FixedDependency, manifest.FixedLibTarget,
+ manifest.FixedBuildTarget)
+
+
# tomllib is present in python 3.11, before that it is a pypi module called tomli,
# we try to import tomllib, then tomli,
# TODO: add a fallback to toml2json?
@@ -54,6 +63,14 @@ else:
toml2json = shutil.which('toml2json')
+_EXTRA_KEYS_WARNING = (
+ "This may (unlikely) be an error in the cargo manifest, or may be a missing "
+ "implementation in Meson. If this issue can be reproduced with the latest "
+ "version of Meson, please help us by opening an issue at "
+ "https://github.com/mesonbuild/meson/issues. Please include the crate and "
+ "version that is generating this warning if possible."
+)
+
class TomlImplementationMissing(MesonException):
pass
@@ -118,6 +135,30 @@ def _fixup_raw_mappings(d: T.Union[manifest.BuildTarget, manifest.LibTarget, man
return T.cast('T.Union[manifest.FixedBuildTarget, manifest.FixedLibTarget, manifest.FixedDependency]', raw)
+def _handle_unknown_keys(data: _UnknownKeysT, cls: T.Union[DataclassInstance, T.Type[DataclassInstance]],
+ msg: str) -> _UnknownKeysT:
+ """Remove and warn on keys that are coming from cargo, but are unknown to
+ our representations.
+
+ This is intended to give users the possibility of things proceeding when a
+ new key is added to Cargo.toml that we don't yet handle, but to still warn
+ them that things might not work.
+
+ :param data: The raw data to look at
+ :param cls: The Dataclass derived type that will be created
+ :param msg: the header for the error message. Usually something like "In N structure".
+ :return: The original data structure, but with all unknown keys removed.
+ """
+ unexpected = set(data) - {x.name for x in dataclasses.fields(cls)}
+ if unexpected:
+ mlog.warning(msg, 'has unexpected keys', '"{}".'.format(', '.join(sorted(unexpected))),
+ _EXTRA_KEYS_WARNING)
+ for k in unexpected:
+ # Mypy and Pyright can't prove that this is okay
+ del data[k] # type: ignore[misc]
+ return data
+
+
@dataclasses.dataclass
class Package:
@@ -160,6 +201,7 @@ class Package:
def from_raw(cls, raw: manifest.Package) -> Self:
pkg = T.cast('manifest.FixedPackage',
{fixup_meson_varname(k): v for k, v in raw.items()})
+ pkg = _handle_unknown_keys(pkg, cls, f'Package entry {pkg["name"]}')
return cls(**pkg)
@dataclasses.dataclass
@@ -240,7 +282,8 @@ class Dependency:
"""Create a dependency from a raw cargo dictionary"""
if isinstance(raw, str):
return cls(name, version.convert(raw))
- return cls(name, **_fixup_raw_mappings(raw))
+ fixed = _handle_unknown_keys(_fixup_raw_mappings(raw), cls, f'Dependency entry {name}')
+ return cls(name, **fixed)
@dataclasses.dataclass
@@ -273,7 +316,8 @@ class BuildTarget:
@classmethod
def from_raw(cls, raw: manifest.BuildTarget) -> Self:
- build = _fixup_raw_mappings(raw)
+ name = raw.get('name', '<anonymous>')
+ build = _handle_unknown_keys(_fixup_raw_mappings(raw), cls, f'Binary entry {name}')
return cls(**build)
@dataclasses.dataclass
@@ -289,13 +333,14 @@ class Library(BuildTarget):
doc_scrape_examples: bool = True
@classmethod
- def from_raw(cls, raw: manifest.LibTarget, fallback_name: str) -> Self:
+ def from_raw(cls, raw: manifest.LibTarget, fallback_name: str) -> Self: # type: ignore[override]
fixed = _fixup_raw_mappings(raw)
# We need to set the name field if it's not set manually, including if
# other fields are set in the lib section
if 'name' not in fixed:
fixed['name'] = fallback_name
+ fixed = _handle_unknown_keys(fixed, cls, f'Library entry {fixed["name"]}')
return cls(**fixed)
diff --git a/test cases/rust/22 cargo subproject/subprojects/bar-0.1-rs/Cargo.toml b/test cases/rust/22 cargo subproject/subprojects/bar-0.1-rs/Cargo.toml
index c0f7ffd8d..d8b4eb26c 100644
--- a/test cases/rust/22 cargo subproject/subprojects/bar-0.1-rs/Cargo.toml
+++ b/test cases/rust/22 cargo subproject/subprojects/bar-0.1-rs/Cargo.toml
@@ -1,6 +1,7 @@
[package]
name = "bar"
version = "0.1"
+flooob = "lolz"
# This dependency does not exist, it is required by default but this subproject
# is called with default-features=false.
diff --git a/test cases/rust/22 cargo subproject/test.json b/test cases/rust/22 cargo subproject/test.json
new file mode 100644
index 000000000..c973b1c91
--- /dev/null
+++ b/test cases/rust/22 cargo subproject/test.json
@@ -0,0 +1,8 @@
+{
+ "stdout": [
+ {
+ "line": "foo-0-rs| WARNING: Package entry bar has unexpected keys \"flooob\". This may (unlikely) be an error in the cargo manifest, or may be a missing implementation in Meson. If this issue can be reproduced with the latest version of Meson, please help us by opening an issue at https://github.com/mesonbuild/meson/issues. Please include the crate and version that is generating this warning if possible."
+ }
+ ]
+}
+