summaryrefslogtreecommitdiff
path: root/mesonbuild/utils/universal.py
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2024-06-30 13:16:42 +0300
committerJussi Pakkanen <jpakkane@gmail.com>2024-07-11 11:53:39 +0300
commit0d7bb776e2d97d406b726b90090bbfa8df13232b (patch)
tree78817e1840f0741439871682b3c25a1e40a3067f /mesonbuild/utils/universal.py
parentc2552527fb2f607052c7aed633b67dbb19f06e38 (diff)
downloadmeson-0d7bb776e2d97d406b726b90090bbfa8df13232b.tar.gz
Move OptionKey in the option source file.
Diffstat (limited to 'mesonbuild/utils/universal.py')
-rw-r--r--mesonbuild/utils/universal.py292
1 files changed, 53 insertions, 239 deletions
diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py
index 4db209a73..b5310b8c3 100644
--- a/mesonbuild/utils/universal.py
+++ b/mesonbuild/utils/universal.py
@@ -15,7 +15,7 @@ import time
import abc
import platform, subprocess, operator, os, shlex, shutil, re
import collections
-from functools import lru_cache, wraps, total_ordering
+from functools import lru_cache, wraps
from itertools import tee
from tempfile import TemporaryDirectory, NamedTemporaryFile
import typing as T
@@ -67,9 +67,7 @@ __all__ = [
'EnvironmentException',
'FileOrString',
'GitException',
- 'OptionKey',
'dump_conf_header',
- 'OptionType',
'OrderedSet',
'PerMachine',
'PerMachineDefaultable',
@@ -1981,7 +1979,58 @@ class LibType(enum.IntEnum):
class ProgressBarFallback: # lgtm [py/iter-returns-non-self]
'''
- Fallback progress bar implementation when tqdm is not found
+ Fallback progress bar implementation when tqdm is not foundclass OptionType(enum.IntEnum):
+
+ """Enum used to specify what kind of argument a thing is."""
+
+ BUILTIN = 0
+ BACKEND = 1
+ BASE = 2
+ COMPILER = 3
+ PROJECT = 4
+
+# This is copied from coredata. There is no way to share this, because this
+# is used in the OptionKey constructor, and the coredata lists are
+# OptionKeys...
+_BUILTIN_NAMES = {
+ 'prefix',
+ 'bindir',
+ 'datadir',
+ 'includedir',
+ 'infodir',
+ 'libdir',
+ 'licensedir',
+ 'libexecdir',
+ 'localedir',
+ 'localstatedir',
+ 'mandir',
+ 'sbindir',
+ 'sharedstatedir',
+ 'sysconfdir',
+ 'auto_features',
+ 'backend',
+ 'buildtype',
+ 'debug',
+ 'default_library',
+ 'errorlogs',
+ 'genvslite',
+ 'install_umask',
+ 'layout',
+ 'optimization',
+ 'prefer_static',
+ 'stdsplit',
+ 'strip',
+ 'unity',
+ 'unity_size',
+ 'warning_level',
+ 'werror',
+ 'wrap_mode',
+ 'force_fallback_for',
+ 'pkg_config_path',
+ 'cmake_prefix_path',
+ 'vsenv',
+}
+
Since this class is not an actual iterator, but only provides a minimal
fallback, it is safe to ignore the 'Iterator does not return self from
@@ -2157,241 +2206,6 @@ def generate_list(func: T.Callable[..., T.Generator[_T, None, None]]) -> T.Calla
return wrapper
-class OptionType(enum.IntEnum):
-
- """Enum used to specify what kind of argument a thing is."""
-
- BUILTIN = 0
- BACKEND = 1
- BASE = 2
- COMPILER = 3
- PROJECT = 4
-
-# This is copied from coredata. There is no way to share this, because this
-# is used in the OptionKey constructor, and the coredata lists are
-# OptionKeys...
-_BUILTIN_NAMES = {
- 'prefix',
- 'bindir',
- 'datadir',
- 'includedir',
- 'infodir',
- 'libdir',
- 'licensedir',
- 'libexecdir',
- 'localedir',
- 'localstatedir',
- 'mandir',
- 'sbindir',
- 'sharedstatedir',
- 'sysconfdir',
- 'auto_features',
- 'backend',
- 'buildtype',
- 'debug',
- 'default_library',
- 'errorlogs',
- 'genvslite',
- 'install_umask',
- 'layout',
- 'optimization',
- 'prefer_static',
- 'stdsplit',
- 'strip',
- 'unity',
- 'unity_size',
- 'warning_level',
- 'werror',
- 'wrap_mode',
- 'force_fallback_for',
- 'pkg_config_path',
- 'cmake_prefix_path',
- 'vsenv',
-}
-
-
-def _classify_argument(key: 'OptionKey') -> OptionType:
- """Classify arguments into groups so we know which dict to assign them to."""
-
- if key.name.startswith('b_'):
- return OptionType.BASE
- elif key.lang is not None:
- return OptionType.COMPILER
- elif key.name in _BUILTIN_NAMES or key.module:
- return OptionType.BUILTIN
- elif key.name.startswith('backend_'):
- assert key.machine is MachineChoice.HOST, str(key)
- return OptionType.BACKEND
- else:
- assert key.machine is MachineChoice.HOST, str(key)
- return OptionType.PROJECT
-
-
-@total_ordering
-class OptionKey:
-
- """Represents an option key in the various option dictionaries.
-
- This provides a flexible, powerful way to map option names from their
- external form (things like subproject:build.option) to something that
- internally easier to reason about and produce.
- """
-
- __slots__ = ['name', 'subproject', 'machine', 'lang', '_hash', 'type', 'module']
-
- name: str
- subproject: str
- machine: MachineChoice
- lang: T.Optional[str]
- _hash: int
- type: OptionType
- module: T.Optional[str]
-
- def __init__(self, name: str, subproject: str = '',
- machine: MachineChoice = MachineChoice.HOST,
- lang: T.Optional[str] = None,
- module: T.Optional[str] = None,
- _type: T.Optional[OptionType] = None):
- # the _type option to the constructor is kinda private. We want to be
- # able tos ave the state and avoid the lookup function when
- # pickling/unpickling, but we need to be able to calculate it when
- # constructing a new OptionKey
- object.__setattr__(self, 'name', name)
- object.__setattr__(self, 'subproject', subproject)
- object.__setattr__(self, 'machine', machine)
- object.__setattr__(self, 'lang', lang)
- object.__setattr__(self, 'module', module)
- object.__setattr__(self, '_hash', hash((name, subproject, machine, lang, module)))
- if _type is None:
- _type = _classify_argument(self)
- object.__setattr__(self, 'type', _type)
-
- def __setattr__(self, key: str, value: T.Any) -> None:
- raise AttributeError('OptionKey instances do not support mutation.')
-
- def __getstate__(self) -> T.Dict[str, T.Any]:
- return {
- 'name': self.name,
- 'subproject': self.subproject,
- 'machine': self.machine,
- 'lang': self.lang,
- '_type': self.type,
- 'module': self.module,
- }
-
- def __setstate__(self, state: T.Dict[str, T.Any]) -> None:
- """De-serialize the state of a pickle.
-
- This is very clever. __init__ is not a constructor, it's an
- initializer, therefore it's safe to call more than once. We create a
- state in the custom __getstate__ method, which is valid to pass
- splatted to the initializer.
- """
- # Mypy doesn't like this, because it's so clever.
- self.__init__(**state) # type: ignore
-
- def __hash__(self) -> int:
- return self._hash
-
- def _to_tuple(self) -> T.Tuple[str, OptionType, str, str, MachineChoice, str]:
- return (self.subproject, self.type, self.lang or '', self.module or '', self.machine, self.name)
-
- def __eq__(self, other: object) -> bool:
- if isinstance(other, OptionKey):
- return self._to_tuple() == other._to_tuple()
- return NotImplemented
-
- def __lt__(self, other: object) -> bool:
- if isinstance(other, OptionKey):
- return self._to_tuple() < other._to_tuple()
- return NotImplemented
-
- def __str__(self) -> str:
- out = self.name
- if self.lang:
- out = f'{self.lang}_{out}'
- if self.machine is MachineChoice.BUILD:
- out = f'build.{out}'
- if self.module:
- out = f'{self.module}.{out}'
- if self.subproject:
- out = f'{self.subproject}:{out}'
- return out
-
- def __repr__(self) -> str:
- return f'OptionKey({self.name!r}, {self.subproject!r}, {self.machine!r}, {self.lang!r}, {self.module!r}, {self.type!r})'
-
- @classmethod
- def from_string(cls, raw: str) -> 'OptionKey':
- """Parse the raw command line format into a three part tuple.
-
- This takes strings like `mysubproject:build.myoption` and Creates an
- OptionKey out of them.
- """
- try:
- subproject, raw2 = raw.split(':')
- except ValueError:
- subproject, raw2 = '', raw
-
- module = None
- for_machine = MachineChoice.HOST
- try:
- prefix, raw3 = raw2.split('.')
- if prefix == 'build':
- for_machine = MachineChoice.BUILD
- else:
- module = prefix
- except ValueError:
- raw3 = raw2
-
- from ..compilers import all_languages
- if any(raw3.startswith(f'{l}_') for l in all_languages):
- lang, opt = raw3.split('_', 1)
- else:
- lang, opt = None, raw3
- assert ':' not in opt
- assert '.' not in opt
-
- return cls(opt, subproject, for_machine, lang, module)
-
- def evolve(self, name: T.Optional[str] = None, subproject: T.Optional[str] = None,
- machine: T.Optional[MachineChoice] = None, lang: T.Optional[str] = '',
- module: T.Optional[str] = '') -> 'OptionKey':
- """Create a new copy of this key, but with altered members.
-
- For example:
- >>> a = OptionKey('foo', '', MachineChoice.Host)
- >>> b = OptionKey('foo', 'bar', MachineChoice.Host)
- >>> b == a.evolve(subproject='bar')
- True
- """
- # We have to be a little clever with lang here, because lang is valid
- # as None, for non-compiler options
- return OptionKey(
- name if name is not None else self.name,
- subproject if subproject is not None else self.subproject,
- machine if machine is not None else self.machine,
- lang if lang != '' else self.lang,
- module if module != '' else self.module
- )
-
- def as_root(self) -> 'OptionKey':
- """Convenience method for key.evolve(subproject='')."""
- return self.evolve(subproject='')
-
- def as_build(self) -> 'OptionKey':
- """Convenience method for key.evolve(machine=MachineChoice.BUILD)."""
- return self.evolve(machine=MachineChoice.BUILD)
-
- def as_host(self) -> 'OptionKey':
- """Convenience method for key.evolve(machine=MachineChoice.HOST)."""
- return self.evolve(machine=MachineChoice.HOST)
-
- def is_project_hack_for_optionsview(self) -> bool:
- """This method will be removed once we can delete OptionsView."""
- return self.type is OptionType.PROJECT
-
-
def pickle_load(filename: str, object_name: str, object_type: T.Type[_PL], suggest_reconfigure: bool = True) -> _PL:
load_fail_msg = f'{object_name} file {filename!r} is corrupted.'
extra_msg = ' Consider reconfiguring the directory with "meson setup --reconfigure".' if suggest_reconfigure else ''