Skip to content

Commit a379a6f

Browse files
committed
fix linting problems & make the module compatible with latest version
1 parent 2edd46b commit a379a6f

4 files changed

Lines changed: 75 additions & 47 deletions

File tree

mesonbuild/modules/features/feature.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import re
44
from typing import (
55
Dict, Set, Tuple, List, Callable, Optional,
6-
Union, Any, Iterable, cast, TYPE_CHECKING
6+
Union, Any, Iterable, TYPE_CHECKING
77
)
88
from dataclasses import dataclass, field
99
from ...mesonlib import File, MesonException
@@ -18,7 +18,6 @@
1818
from typing import TypedDict
1919
from typing_extensions import NotRequired
2020
from ...interpreterbase import TYPE_var, TYPE_kwargs
21-
from ...compilers import Compiler
2221
from .. import ModuleState
2322

2423
@dataclass(unsafe_hash=True, order=True)
@@ -80,7 +79,7 @@ def __init__(self, func_name: str, opt_name: str, default: Any = None):
8079
)
8180

8281
@staticmethod
83-
def convert(func_name:str, opt_name: str, values: 'IMPLIED_ATTR',
82+
def convert(func_name: str, opt_name: str, values: 'IMPLIED_ATTR',
8483
) -> Union[None, List[ConflictAttr]]:
8584
if values is None:
8685
return None
@@ -131,6 +130,7 @@ def convert(func_name:str, opt_name: str, values: 'IMPLIED_ATTR',
131130
Union[str, Dict[str, str]]
132131
]
133132
]
133+
134134
class FeatureKwArgs(TypedDict):
135135
#implies: Optional[List['FeatureObject']]
136136
implies: NotRequired[List[Any]]
@@ -163,7 +163,8 @@ def __init__(self, state: 'ModuleState',
163163
super().__init__()
164164

165165
@typed_pos_args('features.new', str, int)
166-
@typed_kwargs('features.new',
166+
@typed_kwargs(
167+
'features.new',
167168
KwargInfo(
168169
'implies',
169170
(FeatureObject, ContainerTypeInfo(list, FeatureObject)),
@@ -209,7 +210,8 @@ def init_attrs(state: 'ModuleState',
209210
def update_method(self, state: 'ModuleState', args: List['TYPE_var'],
210211
kwargs: 'TYPE_kwargs') -> 'FeatureObject':
211212
@noPosargs
212-
@typed_kwargs('features.FeatureObject.update',
213+
@typed_kwargs(
214+
'features.FeatureObject.update',
213215
KwargInfo('name', (NoneType, str)),
214216
KwargInfo('interest', (NoneType, int)),
215217
KwargInfo(
@@ -306,7 +308,7 @@ def sort_cb(k: Union[FeatureObject, Iterable[FeatureObject]]) -> int:
306308
# FIXME: that's not a safe way to increase the rank for
307309
# multi features this why this function isn't considerd
308310
# accurate.
309-
rank += len(prevalent_features) -1
311+
rank += len(prevalent_features) - 1
310312
return rank
311313
return sorted(features, reverse=reverse, key=sort_cb)
312314

mesonbuild/modules/features/module.py

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from ...interpreter.type_checking import NoneType
1111
from ...interpreterbase.decorators import (
1212
noKwargs, KwargInfo, typed_kwargs, typed_pos_args,
13-
ContainerTypeInfo, permittedKwargs
13+
ContainerTypeInfo
1414
)
1515
from .. import ModuleInfo, NewExtensionModule, ModuleObject
1616
from .feature import FeatureObject, ConflictAttr
@@ -20,7 +20,6 @@
2020
from typing import TypedDict
2121
from ...interpreterbase import TYPE_var, TYPE_kwargs
2222
from .. import ModuleState
23-
from .feature import FeatureKwArgs
2423

2524
class TestKwArgs(TypedDict):
2625
compiler: Optional[Compiler]
@@ -104,11 +103,12 @@ def add_target(self, features: Union[FeatureObject, List[FeatureObject]],
104103
else tuple(sorted(features))
105104
)
106105
targets: List[build.StaticLibrary] = self._targets.setdefault(
107-
tfeatures, cast(List[build.StaticLibrary], [])) # type: ignore
106+
tfeatures, [])
108107
targets.append(target)
109108

110109
class Module(NewExtensionModule):
111110
INFO = ModuleInfo('features', '0.1.0')
111+
112112
def __init__(self) -> None:
113113
super().__init__()
114114
self.methods.update({
@@ -142,7 +142,8 @@ def _set_cache(self, state: 'ModuleState', key: str,
142142
self._cache_dict(state)[key] = val
143143

144144
@typed_pos_args('features.test', varargs=FeatureObject, min_varargs=1)
145-
@typed_kwargs('features.test',
145+
@typed_kwargs(
146+
'features.test',
146147
KwargInfo('compiler', (NoneType, Compiler)),
147148
KwargInfo('anyfet', bool, default = False),
148149
KwargInfo('cached', bool, default = True),
@@ -255,7 +256,7 @@ def test_any(self, state: 'ModuleState', features: Set[FeatureObject],
255256
features_any = set()
256257
for fet in all_features:
257258
_, test_any_result = self.cached_test(
258-
state, features={fet,},
259+
state, features={fet, },
259260
compiler=compiler,
260261
cached=cached,
261262
anyfet=False,
@@ -293,7 +294,7 @@ def test(self, state: 'ModuleState', features: Set[FeatureObject],
293294
# Set the highest interested feature
294295
prevalent_features = sorted(features)[-1:]
295296

296-
prevalent_names = [fet.name for fet in prevalent_features]
297+
prevalent_names = [fet.name for fet in prevalent_features]
297298
# prepare the result dict
298299
test_result: 'TestResultKwArgs' = {
299300
'target_name': '__'.join(prevalent_names),
@@ -307,6 +308,7 @@ def test(self, state: 'ModuleState', features: Set[FeatureObject],
307308
'is_disabled': False,
308309
'fail_reason': '',
309310
}
311+
310312
def fail_result(fail_reason: str, is_disabled: bool = False
311313
) -> 'TestResultKwArgs':
312314
test_result.update({
@@ -337,7 +339,7 @@ def fail_result(fail_reason: str, is_disabled: bool = False
337339
predecessor_features = implied_features.difference(_caller)
338340
for fet in sorted(predecessor_features):
339341
_, pred_result = self.cached_test(
340-
state, features={fet,},
342+
state, features={fet, },
341343
compiler=compiler,
342344
cached=cached,
343345
anyfet=False,
@@ -398,7 +400,7 @@ def fail_result(fail_reason: str, is_disabled: bool = False
398400
test_args = compiler.has_multi_arguments
399401
args = test_result['args']
400402
if args:
401-
supported_args, test_cached = test_args(args, state.environment)
403+
supported_args, test_cached = test_args(args)
402404
if not supported_args:
403405
return fail_result(
404406
f'Arguments "{", ".join(args)}" are not supported'
@@ -423,15 +425,13 @@ def fail_result(fail_reason: str, is_disabled: bool = False
423425
test_result[k].append(extra_name) # type: ignore
424426
return test_result
425427

426-
@permittedKwargs(build.known_stlib_kwargs | {
427-
'dispatch', 'baseline', 'prefix', 'cached', 'keep_sort'
428-
})
429428
@typed_pos_args('features.multi_targets', str, min_varargs=1, varargs=(
430429
str, File, build.CustomTarget, build.CustomTargetIndex,
431430
build.GeneratedList, build.StructuredSources, build.ExtractedObjects,
432431
build.BuildTarget
433432
))
434-
@typed_kwargs('features.multi_targets',
433+
@typed_kwargs(
434+
'features.multi_targets',
435435
KwargInfo(
436436
'dispatch', (
437437
ContainerTypeInfo(list, (FeatureObject, list)),
@@ -451,8 +451,8 @@ def fail_result(fail_reason: str, is_disabled: bool = False
451451
allow_unknown=True
452452
)
453453
def multi_targets_method(self, state: 'ModuleState',
454-
args: Tuple[str], kwargs: 'TYPE_kwargs'
455-
) -> TargetsObject:
454+
args: Tuple[str], kwargs: 'TYPE_kwargs'
455+
) -> TargetsObject:
456456
config_name = args[0]
457457
sources = args[1] # type: ignore
458458
dispatch: List[Union[FeatureObject, List[FeatureObject]]] = (
@@ -467,7 +467,7 @@ def multi_targets_method(self, state: 'ModuleState',
467467
if not compiler:
468468
compiler = get_compiler(state)
469469

470-
baseline_features : Set[FeatureObject] = set()
470+
baseline_features: Set[FeatureObject] = set()
471471
has_baseline = baseline is not None
472472
if has_baseline:
473473
baseline_features = FeatureObject.get_implicit_combine_multi(baseline)
@@ -488,7 +488,7 @@ def multi_targets_method(self, state: 'ModuleState',
488488
]] = []
489489
for d in dispatch:
490490
if isinstance(d, FeatureObject):
491-
target = {d,}
491+
target = {d, }
492492
is_base_part = d in baseline_features
493493
else:
494494
target = set(d)
@@ -647,7 +647,7 @@ def gen_config(self, state: 'ModuleState', config_name: str,
647647
c_detect = '1'
648648
dispatch_calls.append(
649649
f'{prefix}_MTARGETS_EXPAND('
650-
f'EXEC_CB({c_detect}, {test["target_name"]}, __VA_ARGS__)'
650+
f'EXEC_CB({c_detect}, {test["target_name"]}, __VA_ARGS__)'
651651
')'
652652
)
653653

@@ -683,7 +683,8 @@ def gen_config(self, state: 'ModuleState', config_name: str,
683683
return config_path
684684

685685
@typed_pos_args('features.sort', varargs=FeatureObject, min_varargs=1)
686-
@typed_kwargs('features.sort',
686+
@typed_kwargs(
687+
'features.sort',
687688
KwargInfo('reverse', bool, default = False),
688689
)
689690
def sort_method(self, state: 'ModuleState',

mesonbuild/modules/features/utils.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
import hashlib
33
from typing import Tuple, List, Union, Any, TYPE_CHECKING
44
from ...mesonlib import MesonException, MachineChoice
5+
from ...compilers.compilers import CompileCheckMode, Compiler
56

67
if TYPE_CHECKING:
7-
from ...compilers import Compiler
88
from ...mesonlib import File
99
from .. import ModuleState
1010

@@ -27,13 +27,12 @@ def test_code(state: 'ModuleState', compiler: 'Compiler',
2727
) -> Tuple[bool, bool, str]:
2828
# TODO: Add option to treat warnings as errors
2929
with compiler.cached_compile(
30-
code, state.environment.coredata, extra_args=args
30+
code, extra_args=args, mode=CompileCheckMode.COMPILE
3131
) as p:
3232
return p.cached, p.returncode == 0, p.stderr
3333

3434
def generate_hash(*args: Any) -> str:
3535
hasher = hashlib.sha1()
36-
test: List[bytes] = []
3736
for a in args:
3837
hasher.update(bytes(str(a), encoding='utf-8'))
3938
return hasher.hexdigest()

unittests/featurestests.py

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,29 @@
11
# Copyright (c) 2023, NumPy Developers.
22

33
import re
4+
import os
45
import contextlib
6+
from unittest import mock
57
from mesonbuild.interpreter import Interpreter
68
from mesonbuild.build import Build
7-
from mesonbuild.mparser import FunctionNode, ArgumentNode, Token
9+
from mesonbuild.mparser import IdNode, SymbolNode, Token, FunctionNode, ArgumentNode
810
from mesonbuild.modules import ModuleState
911
from mesonbuild.modules.features import Module
1012
from mesonbuild.compilers import Compiler, CompileResult
1113
from mesonbuild.mesonlib import MachineChoice
1214
from mesonbuild.envconfig import MachineInfo
1315

1416
from .baseplatformtests import BasePlatformTests
15-
from run_tests import get_convincing_fake_env_and_cc
17+
from run_tests import FakeBuild, get_fake_env, get_convincing_fake_env_and_cc
1618

1719
class FakeCompiler(Compiler):
1820
language = 'c'
1921

2022
def __init__(self, trap_args = '', trap_code=''):
2123
super().__init__(
2224
ccache=[], exelist=[], version='0.0',
25+
environment=get_fake_env(),
2326
for_machine=MachineChoice.HOST,
24-
info=MachineInfo(
25-
system='linux', cpu_family='x86_64',
26-
cpu='xeon', endian='little',
27-
kernel='linux', subsystem='numpy'
28-
),
29-
is_cross=True
3027
)
3128
self.trap_args = trap_args
3229
self.trap_code = trap_code
@@ -40,7 +37,7 @@ def get_optimization_args(self, optimization_level: str) -> 'T.List[str]':
4037
def get_output_args(self, outputname: str) -> 'T.List[str]':
4138
return []
4239

43-
def has_multi_arguments(self, args: 'T.List[str]', env: 'Environment') -> 'T.Tuple[bool, bool]':
40+
def has_multi_arguments(self, args: 'T.List[str]') -> 'T.Tuple[bool, bool]':
4441
if self.trap_args:
4542
for a in args:
4643
if re.match(self.trap_args, a):
@@ -54,7 +51,13 @@ def compile(self, code: 'mesonlib.FileOrString', *args, **kwargs
5451
rcode = -1
5552
else:
5653
rcode = 0
57-
result = CompileResult(returncode=rcode)
54+
result = CompileResult(
55+
stdout='',
56+
stderr='',
57+
command=[],
58+
returncode=rcode,
59+
input_name='fake_input.c'
60+
)
5861
yield result
5962

6063
@contextlib.contextmanager
@@ -64,28 +67,51 @@ def cached_compile(self, code: 'mesonlib.FileOrString', *args, **kwargs
6467
rcode = -1
6568
else:
6669
rcode = 0
67-
result = CompileResult(returncode=rcode)
70+
result = CompileResult(
71+
stdout='',
72+
stderr='',
73+
command=[],
74+
returncode=rcode,
75+
input_name='fake_input.c'
76+
)
6877
yield result
6978

79+
80+
def _sanity_check_source_code(self) -> str:
81+
return 'public static int main() { return 0; }'
82+
7083
class FeaturesTests(BasePlatformTests):
84+
85+
@mock.patch.dict(os.environ)
86+
@mock.patch.object(Interpreter, 'load_root_meson_file', mock.Mock(return_value=None))
87+
@mock.patch.object(Interpreter, 'sanity_check_ast', mock.Mock(return_value=None))
88+
@mock.patch.object(Interpreter, 'parse_project', mock.Mock(return_value=None))
7189
def setUp(self):
7290
super().setUp()
7391
env, cc = get_convincing_fake_env_and_cc(
7492
bdir=self.builddir, prefix=self.prefix)
7593
env.machines.target = env.machines.host
7694

95+
# Disable unit test specific syntax
96+
os.environ.pop('MESON_RUNNING_IN_PROJECT_TESTS', None)
7797
build = Build(env)
78-
interp = Interpreter(build, mock=True)
98+
interp = Interpreter(build)
99+
# Mock out user_defined_options to bypass the coredata initialization crash
100+
interp.user_defined_options = mock.Mock()
101+
interp.user_defined_options.cmd_line_options = {}
102+
79103
project = interp.funcs['project']
80104
filename = 'featurestests.py'
105+
dummy_span = (0, 0) # Safe placeholder for bytespan: Tuple[int, int]
106+
func_name_token = Token('id', filename, 0, 0, 0, dummy_span, 'FeaturesTests')
107+
lpar_token = Token('lpar', filename, 0, 0, 13, dummy_span, '(')
108+
arg_token = Token('string', filename, 0, 0, 14, dummy_span, '')
109+
rpar_token = Token('rpar', filename, 0, 0, 15, dummy_span, ')')
81110
node = FunctionNode(
82-
filename = filename,
83-
lineno = 0,
84-
colno = 0,
85-
end_lineno = 0,
86-
end_colno = 0,
87-
func_name = 'FeaturesTests',
88-
args = ArgumentNode(Token('string', filename, 0, 0, 0, None, ''))
111+
IdNode(func_name_token),
112+
SymbolNode(lpar_token),
113+
ArgumentNode(arg_token),
114+
SymbolNode(rpar_token)
89115
)
90116
project(node, ['Test Module Features'], {'version': '0.1'})
91117
self.cc = cc
@@ -272,7 +298,7 @@ def test_conflict_args(self):
272298
),
273299
(
274300
[fet6],
275-
'args', {'val':'arch=', 'match': 'arg.*[0-9]|arch=.*', 'mfilter': '([0-9])|arch=(\w+)', 'mjoin': '*'},
301+
'args', {'val':'arch=', 'match': 'arg.*[0-9]|arch=.*', 'mfilter': r'([0-9])|arch=(\w+)', 'mjoin': '*'},
276302
['arch=1*2*3*4*5*xx'],
277303
),
278304
(

0 commit comments

Comments
 (0)