summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSalamandar <felix@piedallu.me>2018-04-26 16:49:13 +0200
committerSalamandar <felix@piedallu.me>2018-06-01 14:23:24 +0200
commitae19fec9528c0e3ff764eca271227c670284909a (patch)
treed91fc8bbfad239abe5e5b306a5a1eff40f844fbd
parentee2f8a0416f6973d03d36601f5dd99db7825ef7f (diff)
downloadmeson-ae19fec9528c0e3ff764eca271227c670284909a.tar.gz
Add version_compare_condition_with_{min,max} for specific comparison utils.
Split FeatureNew and FeatureDeprecated Implement features report to be printed in some 'dev mode'
-rw-r--r--mesonbuild/interpreter.py1
-rw-r--r--mesonbuild/interpreterbase.py60
-rw-r--r--mesonbuild/mesonlib.py68
3 files changed, 125 insertions, 4 deletions
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 21f66cdea..46f180349 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -28,6 +28,7 @@ from .interpreterbase import InterpreterBase
from .interpreterbase import check_stringlist, flatten, noPosargs, noKwargs, stringArgs, permittedKwargs, noArgsFlattening
from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest
from .interpreterbase import InterpreterObject, MutableInterpreterObject, Disabler
+from .interpreterbase import FeatureNew, FeatureDeprecated
from .modules import ModuleReturnValue
import os, sys, shutil, uuid
diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py
index 52dad724d..00cb9dd01 100644
--- a/mesonbuild/interpreterbase.py
+++ b/mesonbuild/interpreterbase.py
@@ -124,22 +124,74 @@ class permittedKwargs:
return f(*wrapped_args, **wrapped_kwargs)
return wrapped
-class featureVersion:
- """Checks for newer/deprecated features"""
+class FeatureNew:
+ """Checks for new features"""
+ # Shared across all instances
+ min_feature_versions = dict()
- def __init__(self, feature_name, wanted_version):
+ def __init__(self, feature_name, first_version):
self.feature_name = feature_name
- self.wanted_version = wanted_version
+ self.feature_version = first_version
+
+ def add_called_feature(self):
+ if self.feature_version not in self.min_feature_versions:
+ self.min_feature_versions[self.feature_version] = []
+ self.min_feature_versions[self.feature_version].append(self.feature_name)
+
+ def called_features_report():
+ print('Minimum version of features used:')
+ for version in sorted(FeatureNew.min_feature_versions.keys()):
+ print('{}: {}'.format(version, FeatureNew.min_feature_versions[version]))
def __call__(self, f):
@wraps(f)
def wrapped(*wrapped_args, **wrapped_kwargs):
+ self.add_called_feature()
tv = coredata.target_version
if tv == '':
return
+ if not mesonlib.version_compare_condition_with_min(tv, self.feature_version):
+ mlog.error(
+ '''Project targetting \'{}\' but tried to use feature introduced in \'{}\': {}'''
+ .format(tv, self.feature_version, self.feature_name))
return f(*wrapped_args, **wrapped_kwargs)
return wrapped
+class FeatureDeprecated:
+ """Checks for deprecated features"""
+ # Shared across all instances
+ max_feature_versions = dict()
+
+ def __init__(self, feature_name, first_version):
+ self.feature_name = feature_name
+ self.feature_version = first_version
+
+ def add_called_feature(self):
+ if self.feature_version not in self.max_feature_versions:
+ self.max_feature_versions[self.feature_version] = []
+ self.max_feature_versions[self.feature_version].append(self.feature_name)
+
+ def called_features_report():
+ print('Deprecated features used:')
+ for version in sorted(FeatureDeprecated.max_feature_versions.keys()):
+ print('{}: {}'.format(version, FeatureDeprecated.max_feature_versions[version]))
+
+ def __call__(self, f):
+ @wraps(f)
+ def wrapped(*wrapped_args, **wrapped_kwargs):
+ print('deprecated:', self.feature_name, self.feature_version)
+ self.add_called_feature()
+ tv = coredata.target_version
+ if tv == '':
+ return
+ if not mesonlib.version_compare_condition_with_max(tv, self.feature_version):
+ mlog.error(
+ '''Project targetting \'{}\' but tried to use feature deprecated since \'{}\': {}'''
+ .format(tv, self.feature_version, self.feature_name))
+ return f(*wrapped_args, **wrapped_kwargs)
+ return wrapped
+
+
class InterpreterException(mesonlib.MesonException):
pass
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index fe426c574..a2f05bc34 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -487,6 +487,74 @@ def version_compare_many(vstr1, conditions):
found.append(req)
return not_found == [], not_found, found
+
+def version_compare_condition_with_min(condition, minimum):
+ match = numpart.match(minimum.strip())
+ if match is None:
+ msg = 'Uncomparable version string {!r}.'
+ raise MesonException(msg.format(minimum))
+ minimum = match.group(0)
+ if condition.startswith('>='):
+ cmpop = operator.lt
+ condition = condition[2:]
+ elif condition.startswith('<='):
+ return True
+ condition = condition[2:]
+ elif condition.startswith('!='):
+ return True
+ condition = condition[2:]
+ elif condition.startswith('=='):
+ cmpop = operator.lt
+ condition = condition[2:]
+ elif condition.startswith('='):
+ cmpop = operator.lt
+ condition = condition[1:]
+ elif condition.startswith('>'):
+ cmpop = operator.lt
+ condition = condition[1:]
+ elif condition.startswith('<'):
+ return True
+ condition = condition[2:]
+ else:
+ cmpop = operator.eq
+ varr1 = grab_leading_numbers(minimum, True)
+ varr2 = grab_leading_numbers(condition, True)
+ return cmpop(varr1, varr2)
+
+def version_compare_condition_with_max(condition, maximum):
+ match = numpart.match(maximum.strip())
+ if match is None:
+ msg = 'Uncomparable version string {!r}.'
+ raise MesonException(msg.format(maximum))
+ maximum = match.group(0)
+ if condition.startswith('>='):
+ return False
+ condition = condition[2:]
+ elif condition.startswith('<='):
+ cmpop = operator.lt
+ condition = condition[2:]
+ elif condition.startswith('!='):
+ return False
+ condition = condition[2:]
+ elif condition.startswith('=='):
+ cmpop = operator.lt
+ condition = condition[2:]
+ elif condition.startswith('='):
+ cmpop = operator.lt
+ condition = condition[1:]
+ elif condition.startswith('>'):
+ return False
+ condition = condition[1:]
+ elif condition.startswith('<'):
+ cmpop = operator.lt
+ condition = condition[2:]
+ else:
+ cmpop = operator.eq
+ varr1 = grab_leading_numbers(maximum, True)
+ varr2 = grab_leading_numbers(condition, True)
+ return cmpop(varr1, varr2)
+
+
def default_libdir():
if is_debianlike():
try: