Skip to content

Commit

Permalink
Fix unit tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
jpakkane committed Aug 2, 2024
1 parent cd82c72 commit eec4182
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 49 deletions.
33 changes: 0 additions & 33 deletions mesonbuild/coredata.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,39 +356,6 @@ def builtin_options_libdir_cross_fixup(self) -> None:
if self.cross_files:
options.BUILTIN_OPTIONS[OptionKey('libdir')].default = 'lib'


def sanitize_dir_option_value(self, prefix: str, option: OptionKey, value: T.Any) -> T.Any:
'''
If the option is an installation directory option, the value is an
absolute path and resides within prefix, return the value
as a path relative to the prefix. Otherwise, return it as is.
This way everyone can do f.ex, get_option('libdir') and usually get
the library directory relative to prefix, even though it really
should not be relied upon.
'''
try:
value = PurePath(value)
except TypeError:
return value
if option.name.endswith('dir') and value.is_absolute() and \
option not in options.BUILTIN_DIR_NOPREFIX_OPTIONS:
try:
# Try to relativize the path.
value = value.relative_to(prefix)
except ValueError:
# Path is not relative, let’s keep it as is.
pass
if '..' in value.parts:
raise MesonException(
f'The value of the \'{option}\' option is \'{value}\' but '
'directory options are not allowed to contain \'..\'.\n'
f'If you need a path outside of the {prefix!r} prefix, '
'please use an absolute path.'
)
# .as_posix() keeps the posix-like file separators Meson uses.
return value.as_posix()

def init_builtins(self, subproject: str) -> None:
# Create builtin options with default values
for key, opt in options.BUILTIN_OPTIONS.items():
Expand Down
8 changes: 6 additions & 2 deletions mesonbuild/mconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,11 +386,15 @@ def run_impl(options: CMDOptions, builddir: str) -> int:

save = False
if has_option_flags(options):
if hasattr(options.A):
if hasattr(options, 'A'):
A = options.A
else:
A = []
save |= c.coredata.optstore.set_from_configure_command(options.projectoptions, A, options.U)
if hasattr(options, 'U'):
U = options.U
else:
U = []
save |= c.coredata.optstore.set_from_configure_command(options.projectoptions, A, U)
coredata.update_cmd_line_file(builddir, options)
if options.clearcache:
c.clear_cache()
Expand Down
10 changes: 9 additions & 1 deletion mesonbuild/mintro.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,15 @@ def add_keys(opts: 'T.Union[dict[OptionKey, UserOption[Any]], cdata.KeyedOptionD
'compiler',
)
add_keys(dir_options, 'directory')
add_keys({k: v for k, v in coredata.optstore.items() if coredata.optstore.is_project_option(k)}, 'user')

def project_option_key_to_introname(key: OptionKey):
assert key.subproject is not None
if key.subproject == '':
return key.evolve(subproject=None)
return key

add_keys({project_option_key_to_introname(k): v \
for k, v in coredata.optstore.items() if coredata.optstore.is_project_option(k)}, 'user')
add_keys(test_options, 'test')
return optlist

Expand Down
54 changes: 45 additions & 9 deletions mesonbuild/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import re
import itertools
import os
import pathlib

from .mesonlib import (
HoldableObject,
Expand Down Expand Up @@ -768,7 +769,6 @@ def add_system_option_internal(self, key: T.Union[OptionKey, str], valobj: 'User
if pval is not None:
self.set_option(key.name, key.subproject, pval)


def add_compiler_option(self, language: str, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'):
key = self.ensure_and_validate_key(key)
if not key.name.startswith(language + '_'):
Expand All @@ -779,11 +779,14 @@ def add_project_option(self, key: OptionKey, valobj: 'UserOption[T.Any]'):
assert ':' not in key.name
assert '.' not in key.name
assert key.subproject is not None
self.options[key] = valobj
self.project_options.add(key)
pval = self.pending_project_options.pop(key, None)
if pval is not None:
self.set_option(key.name, key.subproject, pval)
if key in self.options:
raise MesonException(f'Internal error: tried to add a project option {key} that already exists.')
else:
self.options[key] = valobj
self.project_options.add(key)
if pval is not None:
self.set_option(key.name, key.subproject, pval)

def add_module_option(self, modulename: str, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'):
key = self.ensure_and_validate_key(key)
Expand Down Expand Up @@ -811,12 +814,45 @@ def sanitize_prefix(self, prefix: str) -> str:
prefix = prefix[:-1]
return prefix

def sanitize_dir_option_value(self, prefix: str, option: OptionKey, value: T.Any) -> T.Any:
'''
If the option is an installation directory option, the value is an
absolute path and resides within prefix, return the value
as a path relative to the prefix. Otherwise, return it as is.
This way everyone can do f.ex, get_option('libdir') and usually get
the library directory relative to prefix, even though it really
should not be relied upon.
'''
try:
value = pathlib.PurePath(value)
except TypeError:
return value
if option.name.endswith('dir') and value.is_absolute() and \
option not in options.BUILTIN_DIR_NOPREFIX_OPTIONS:
try:
# Try to relativize the path.
value = value.relative_to(prefix)
except ValueError:
# Path is not relative, let’s keep it as is.
pass
if '..' in value.parts:
raise MesonException(
f'The value of the \'{option}\' option is \'{value}\' but '
'directory options are not allowed to contain \'..\'.\n'
f'If you need a path outside of the {prefix!r} prefix, '
'please use an absolute path.'
)
# .as_posix() keeps the posix-like file separators Meson uses.
return value.as_posix()


def set_value(self, key: T.Union[OptionKey, str], new_value: 'T.Any') -> bool:
key = self.ensure_and_validate_key(key)
if key.name == 'prefix':
new_value = self.sanitize_prefix(new_value)
elif self.is_builtin_option(key):
prefix = self.optstore.get_value_for('prefix')
prefix = self.get_value_for('prefix')
new_value = self.sanitize_dir_option_value(prefix, key, new_value)
if key not in self.options:
raise MesonException(f'Internal error, tried to access non-existing option {key.name}.')
Expand Down Expand Up @@ -966,9 +1002,9 @@ def get_value_for(self, name, subproject=None):
def set_option_from_string(self, keystr, new_value):
o = OptionKey.from_string(keystr)
if o in self.options:
return self.set_value(o.name, o.subproject, new_value)
o = o.copy_with(subproject='')
return self.set_value(o.name, o.subproject, new_value)
return self.set_value(o, new_value)
o = o.evolve(subproject='')
return self.set_value(o, new_value)

def set_subproject_options(self, subproject, spcall_default_options, project_default_options):
for o in itertools.chain(spcall_default_options, project_default_options):
Expand Down
6 changes: 4 additions & 2 deletions test cases/common/40 options/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ if get_option('integer_opt') != 3
error('Incorrect value in integer option.')
endif

if get_option('neg_int_opt') != -3
error('Incorrect value in negative integer option.')
negint = get_option('neg_int_opt')

if negint != -3 and negint != -10
error('Incorrect value @0@ in negative integer option.'.format(negint))
endif

if get_option('CaseSenSiTivE') != 'Some CAPS'
Expand Down
3 changes: 1 addition & 2 deletions unittests/platformagnostictests.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def test_relative_find_program(self):
self.init(testdir, workdir=testdir)

def test_invalid_option_names(self):
store = OptionStore()
store = OptionStore(False)
interp = OptionInterpreter(store, '')

def write_file(code: str):
Expand Down Expand Up @@ -352,7 +352,6 @@ def test_reconfigure_base_options(self):
self.assertIn('\nMessage: c_std: c89\n', out)

out = self.init(testdir, extra_args=['--reconfigure', '-Db_ndebug=if-release', '-Dsub:b_ndebug=false', '-Dc_std=c99', '-Dsub:c_std=c11'])
raise RuntimError(out)
self.assertIn('\nMessage: b_ndebug: if-release\n', out)
self.assertIn('\nMessage: c_std: c99\n', out)
self.assertIn('\nMessage: sub:b_ndebug: false\n', out)
Expand Down

0 comments on commit eec4182

Please sign in to comment.