files: # Copyright 2012-2018 The Meson development team
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  
  #     http://www.apache.org/licenses/LICENSE-2.0
  
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  from . import mparser
  from . import environment
  from . import coredata
  from . import dependencies
  from . import mlog
  from . import build
  from . import optinterpreter
  from . import compilers
  from .wrap import wrap, WrapMode
  from . import mesonlib
  from .mesonlib import FileMode, Popen_safe, listify, extract_as_list, has_path_sep
  from .dependencies import ExternalProgram
  from .dependencies import InternalDependency, Dependency, NotFoundDependency, DependencyException
  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, FeatureNewKwargs
  from .modules import ModuleReturnValue
  
  import os, sys, shutil, uuid
  import re, shlex
  import subprocess
  from collections import namedtuple
  from pathlib import PurePath
  
  import importlib
  
  permitted_method_kwargs = {
      'partial_dependency': {'compile_args', 'link_args', 'links', 'includes',
                             'sources'},
  }
  
  def stringifyUserArguments(args):
      if isinstance(args, list):
          return '[%s]' % ', '.join([stringifyUserArguments(x) for x in args])
      elif isinstance(args, dict):
          return '{%s}' % ', '.join(['%s : %s' % (stringifyUserArguments(k), stringifyUserArguments(v)) for k, v in args.items()])
      elif isinstance(args, int):
          return str(args)
      elif isinstance(args, str):
          return "'%s'" % args
      raise InvalidArguments('Function accepts only strings, integers, lists and lists thereof.')
  
  
  class ObjectHolder:
      def __init__(self, obj):
          self.held_object = obj
  
      def __repr__(self):
          return '<Holder: {!r}>'.format(self.held_object)
  
  class FeatureOptionHolder(InterpreterObject, ObjectHolder):
      def __init__(self, env, option):
          InterpreterObject.__init__(self)
          ObjectHolder.__init__(self, option)
          if option.is_auto():
              self.held_object = env.coredata.builtins['auto_features']
          self.name = option.name
          self.methods.update({'enabled': self.enabled_method,
                               'disabled': self.disabled_method,
                               'auto': self.auto_method,
                               })
  
      @noPosargs
      @permittedKwargs({})
      def enabled_method(self, args, kwargs):
          return self.held_object.is_enabled()
  
      @noPosargs
      @permittedKwargs({})
      def disabled_method(self, args, kwargs):
          return self.held_object.is_disabled()
  
      @noPosargs
      @permittedKwargs({})
      def auto_method(self, args, kwargs):
          return self.held_object.is_auto()
  
  def extract_required_kwarg(kwargs):
      val = kwargs.get('required', True)
      disabled = False
      required = False
      feature = None
      if isinstance(val, FeatureOptionHolder):
          option = val.held_object
          feature = val.name
          if option.is_disabled():
              disabled = True
          elif option.is_enabled():
              required = True
      elif isinstance(required, bool):
          required = val
      else:
          raise InterpreterException('required keyword argument must be boolean or a feature option')
  
      # Keep boolean value in kwargs to simplify other places where this kwarg is
      # checked.
      kwargs['required'] = required
  
      return disabled, required, feature
  
  class TryRunResultHolder(InterpreterObject):
      def __init__(self, res):
          super().__init__()
          self.res = res
          self.methods.update({'returncode': self.returncode_method,
                               'compiled': self.compiled_method,
                               'stdout': self.stdout_method,
                               'stderr': self.stderr_method,
                               })
  
      @noPosargs
      @permittedKwargs({})
      def returncode_method(self, args, kwargs):
          return self.res.returncode
  
      @noPosargs
      @permittedKwargs({})
      def compiled_method(self, args, kwargs):
          return self.res.compiled
  
      @noPosargs
      @permittedKwargs({})
      def stdout_method(self, args, kwargs):
          return self.res.stdout
  
      @noPosargs
      @permittedKwargs({})
      def stderr_method(self, args, kwargs):
          return self.res.stderr
  
  class RunProcess(InterpreterObject):
  
      def __init__(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False, check=False, capture=True):
          super().__init__()
          if not isinstance(cmd, ExternalProgram):
              raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
          self.capture = capture
          pc, self.stdout, self.stderr = self.run_command(cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check)
          self.returncode = pc.returncode
          self.methods.update({'returncode': self.returncode_method,
                               'stdout': self.stdout_method,
                               'stderr': self.stderr_method,
                               })
  
      def run_command(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check=False):
          command_array = cmd.get_command() + args
          env = {'MESON_SOURCE_ROOT': source_dir,
                 'MESON_BUILD_ROOT': build_dir,
                 'MESON_SUBDIR': subdir,
                 'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in mesonintrospect]),
                 }
          if in_builddir:
              cwd = os.path.join(build_dir, subdir)
          else:
              cwd = os.path.join(source_dir, subdir)
          child_env = os.environ.copy()
          child_env.update(env)
          stdout = subprocess.PIPE if self.capture else subprocess.DEVNULL
          mlog.debug('Running command:', ' '.join(command_array))
          try:
              p, o, e = Popen_safe(command_array, stdout=stdout, env=child_env, cwd=cwd)
              if self.capture:
                  mlog.debug('--- stdout ---')
                  mlog.debug(o)
              else:
                  o = ''
                  mlog.debug('--- stdout disabled ---')
              mlog.debug('--- stderr ---')
              mlog.debug(e)
              mlog.debug('')
  
              if check and p.returncode != 0:
                  raise InterpreterException('Command "{}" failed with status {}.'.format(' '.join(command_array), p.returncode))
  
              return p, o, e
          except FileNotFoundError:
              raise InterpreterException('Could not execute command "%s".' % ' '.join(command_array))
  
      @noPosargs
      @permittedKwargs({})
      def returncode_method(self, args, kwargs):
          return self.returncode
  
      @noPosargs
      @permittedKwargs({})
      def stdout_method(self, args, kwargs):
          return self.stdout
  
      @noPosargs
      @permittedKwargs({})
      def stderr_method(self, args, kwargs):
          return self.stderr
  
  class ConfigureFileHolder(InterpreterObject, ObjectHolder):
  
      def __init__(self, subdir, sourcename, targetname, configuration_data):
          InterpreterObject.__init__(self)
          ObjectHolder.__init__(self, build.ConfigureFile(subdir, sourcename,
                                                          targetname, configuration_data))
  
  
  class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder):
      def __init__(self):
          MutableInterpreterObject.__init__(self)
          ObjectHolder.__init__(self, build.EnvironmentVariables())
          self.methods.update({'set': self.set_method,
                               'append': self.append_method,
                               'prepend': self.prepend_method,
                               })
  
      def __repr__(self):
          repr_str = "<{0}: {1}>"
          return repr_str.format(self.__class__.__name__, self.held_object.envvars)
  
      def add_var(self, method, args, kwargs):
          if not isinstance(kwargs.get("separator", ""), str):
              raise InterpreterException("EnvironmentVariablesHolder methods 'separator'"
                                         " argument needs to be a string.")
          if len(args) < 2:
              raise InterpreterException("EnvironmentVariablesHolder methods require at least"
                                         "2 arguments, first is the name of the variable and"
                                         " following one are values")
          self.held_object.envvars.append((method, args[0], args[1:], kwargs))
  
      @stringArgs
      @permittedKwargs({'separator'})
      def set_method(self, args, kwargs):
          self.add_var(self.held_object.set, args, kwargs)
  
      @stringArgs
      @permittedKwargs({'separator'})
      def append_method(self, args, kwargs):
          self.add_var(self.held_object.append, args, kwargs)
  
      @stringArgs
      @permittedKwargs({'separator'})
      def prepend_method(self, args, kwargs):
          self.add_var(self.held_object.prepend, args, kwargs)
  
  
  class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder):
      def __init__(self):
          MutableInterpreterObject.__init__(self)
          self.used = False # These objects become immutable after use in configure_file.
          ObjectHolder.__init__(self, build.ConfigurationData())
          self.methods.update({'set': self.set_method,
                               'set10': self.set10_method,
                               'set_quoted': self.set_quoted_method,
                               'has': self.has_method,
                               'get': self.get_method,
                               'get_unquoted': self.get_unquoted_method,
                               'merge_from': self.merge_from_method,
                               })
  
      def is_used(self):
          return self.used
  
      def mark_used(self):
          self.used = True
  
      def validate_args(self, args, kwargs):
          if len(args) == 1 and isinstance(args[0], list) and len(args[0]) == 2:
              mlog.log(mlog.red('DEPRECATION:'),
                       '''Passing a list as the single argument to configuration_data.set is deprecated.
  This will become a hard error in the future''')
              args = args[0]
  
          if len(args) != 2:
              raise InterpreterException("Configuration set requires 2 arguments.")
          if self.used:
              raise InterpreterException("Can not set values on configuration object that has been used.")
          name = args[0]
          val = args[1]
          desc = kwargs.get('description', None)
          if not isinstance(name, str):
              raise InterpreterException("First argument to set must be a string.")
          if desc is not None and not isinstance(desc, str):
              raise InterpreterException('Description must be a string.')
  
          return name, val, desc
  
      @noArgsFlattening
      def set_method(self, args, kwargs):
          (name, val, desc) = self.validate_args(args, kwargs)
          self.held_object.values[name] = (val, desc)
  
      def set_quoted_method(self, args, kwargs):
          (name, val, desc) = self.validate_args(args, kwargs)
          if not isinstance(val, str):
              raise InterpreterException("Second argument to set_quoted must be a string.")
          escaped_val = '\\"'.join(val.split('"'))
          self.held_object.values[name] = ('"' + escaped_val + '"', desc)
  
      def set10_method(self, args, kwargs):
          (name, val, desc) = self.validate_args(args, kwargs)
          if val:
              self.held_object.values[name] = (1, desc)
          else:
              self.held_object.values[name] = (0, desc)
  
      def has_method(self, args, kwargs):
          return args[0] in self.held_object.values
  
      @FeatureNew('configuration_data.get()', '0.38.0')
      @noArgsFlattening
      def get_method(self, args, kwargs):
          if len(args) < 1 or len(args) > 2:
              raise InterpreterException('Get method takes one or two arguments.')
          name = args[0]
          if name in self.held_object:
              return self.held_object.get(name)[0]
          if len(args) > 1:
              return args[1]
          raise InterpreterException('Entry %s not in configuration data.' % name)
  
      @FeatureNew('get_unquoted', '0.44.0')
      def get_unquoted_method(self, args, kwargs):
          if len(args) < 1 or len(args) > 2:
              raise InterpreterException('Get method takes one or two arguments.')
          name = args[0]
          if name in self.held_object:
              val = self.held_object.get(name)[0]
          elif len(args) > 1:
              val = args[1]
          else:
              raise InterpreterException('Entry %s not in configuration data.' % name)
          if val[0] == '"' and val[-1] == '"':
              return val[1:-1]
          return val
  
      def get(self, name):
          return self.held_object.values[name] # (val, desc)
  
      def keys(self):
          return self.held_object.values.keys()
  
      def merge_from_method(self, args, kwargs):
          if len(args) != 1:
              raise InterpreterException('Merge_from takes one positional argument.')
          from_object = args[0]
          if not isinstance(from_object, ConfigurationDataHolder):
              raise InterpreterException('Merge_from argument must be a configuration data object.')
          from_object = from_object.held_object
          for k, v in from_object.values.items():
              self.held_object.values[k] = v
  
  # Interpreter objects can not be pickled so we must have
  # these wrappers.
  
  class DependencyHolder(InterpreterObject, ObjectHolder):
      def __init__(self, dep):
          InterpreterObject.__init__(self)
          ObjectHolder.__init__(self, dep)
          self.methods.update({'found': self.found_method,
                               'type_name': self.type_name_method,
                               'version': self.version_method,
                               'get_pkgconfig_variable': self.pkgconfig_method,
                               'get_configtool_variable': self.configtool_method,
                               'partial_dependency': self.partial_dependency_method,
                               })
  
      @noPosargs
      @permittedKwargs({})
      def type_name_method(self, args, kwargs):
          return self.held_object.type_name
  
      @noPosargs
      @permittedKwargs({})
      def found_method(self, args, kwargs):
          if self.held_object.type_name == 'internal':
              return True
          return self.held_object.found()
  
      @noPosargs
      @permittedKwargs({})
      def version_method(self, args, kwargs):
          return self.held_object.get_version()
  
      @permittedKwargs({'define_variable'})
      def pkgconfig_method(self, args, kwargs):
          args = listify(args)
          if len(args) != 1:
              raise InterpreterException('get_pkgconfig_variable takes exactly one argument.')
          varname = args[0]
          if not isinstance(varname, str):
              raise InterpreterException('Variable name must be a string.')
          return self.held_object.get_pkgconfig_variable(varname, kwargs)
  
      @FeatureNew('get_configtool_variable', '0.44.0')
      @permittedKwargs({})
      def configtool_method(self, args, kwargs):
          args = listify(args)
          if len(args) != 1:
              raise InterpreterException('get_configtool_variable takes exactly one argument.')
          varname = args[0]
          if not isinstance(varname, str):
              raise InterpreterException('Variable name must be a string.')
          return self.held_object.get_configtool_variable(varname)
  
      @FeatureNew('dep.partial_dependency', '0.46.0')
      @noPosargs
      @permittedKwargs(permitted_method_kwargs['partial_dependency'])
      def partial_dependency_method(self, args, kwargs):
          return DependencyHolder(self.held_object.get_partial_dependency(**kwargs))
  
  class InternalDependencyHolder(InterpreterObject, ObjectHolder):
      def __init__(self, dep):
          InterpreterObject.__init__(self)
          ObjectHolder.__init__(self, dep)
          self.methods.update({'found': self.found_method,
                               'version': self.version_method,
                               'partial_dependency': self.partial_dependency_method,
                               })
  
      @noPosargs
      @permittedKwargs({})
      def found_method(self, args, kwargs):
          return True
  
      @noPosargs
      @permittedKwargs({})
      def version_method(self, args, kwargs):
          return self.held_object.get_version()
  
      @FeatureNew('dep.partial_dependency', '0.46.0')
      @noPosargs
      @permittedKwargs(permitted_method_kwargs['partial_dependency'])
      def partial_dependency_method(self, args, kwargs):
          return DependencyHolder(self.held_object.get_partial_dependency(**kwargs))
  
  class ExternalProgramHolder(InterpreterObject, ObjectHolder):
      def __init__(self,
  
  [... the rest is omitted ...]
files: mesonbuild/interpreter.py
files: # Copyright 2012-2018 The Meson development team
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  
  #     http://www.apache.org/licenses/LICENSE-2.0
  
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  from . import mparser
  from . import environment
  from . import coredata
  from . import dependencies
  from . import mlog
  from . import build
  from . import optinterpreter
  from . import compilers
  from .wrap import wrap, WrapMode
  from . import mesonlib
  from .mesonlib import FileMode, Popen_safe, listify, extract_as_list, has_path_sep
  from .dependencies import ExternalProgram
  from .dependencies import InternalDependency, Dependency, NotFoundDependency, DependencyException
  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, FeatureNewKwargs
  from .modules import ModuleReturnValue
  
  import os, sys, shutil, uuid
  import re, shlex
  import subprocess
  from collections import namedtuple
  from pathlib import PurePath
  
  import importlib
  
  permitted_method_kwargs = {
      'partial_dependency': {'compile_args', 'link_args', 'links', 'includes',
                             'sources'},
  }
  
  def stringifyUserArguments(args):
      if isinstance(args, list):
          return '[%s]' % ', '.join([stringifyUserArguments(x) for x in args])
      elif isinstance(args, dict):
          return '{%s}' % ', '.join(['%s : %s' % (stringifyUserArguments(k), stringifyUserArguments(v)) for k, v in args.items()])
      elif isinstance(args, int):
          return str(args)
      elif isinstance(args, str):
          return "'%s'" % args
      raise InvalidArguments('Function accepts only strings, integers, lists and lists thereof.')
  
  
  class ObjectHolder:
      def __init__(self, obj):
          self.held_object = obj
  
      def __repr__(self):
          return '<Holder: {!r}>'.format(self.held_object)
  
  class FeatureOptionHolder(InterpreterObject, ObjectHolder):
      def __init__(self, env, option):
          InterpreterObject.__init__(self)
          ObjectHolder.__init__(self, option)
          if option.is_auto():
              self.held_object = env.coredata.builtins['auto_features']
          self.name = option.name
          self.methods.update({'enabled': self.enabled_method,
                               'disabled': self.disabled_method,
                               'auto': self.auto_method,
                               })
  
      @noPosargs
      @permittedKwargs({})
      def enabled_method(self, args, kwargs):
          return self.held_object.is_enabled()
  
      @noPosargs
      @permittedKwargs({})
      def disabled_method(self, args, kwargs):
          return self.held_object.is_disabled()
  
      @noPosargs
      @permittedKwargs({})
      def auto_method(self, args, kwargs):
          return self.held_object.is_auto()
  
  def extract_required_kwarg(kwargs):
      val = kwargs.get('required', True)
      disabled = False
      required = False
      feature = None
      if isinstance(val, FeatureOptionHolder):
          option = val.held_object
          feature = val.name
          if option.is_disabled():
              disabled = True
          elif option.is_enabled():
              required = True
      elif isinstance(required, bool):
          required = val
      else:
          raise InterpreterException('required keyword argument must be boolean or a feature option')
  
      # Keep boolean value in kwargs to simplify other places where this kwarg is
      # checked.
      kwargs['required'] = required
  
      return disabled, required, feature
  
  class TryRunResultHolder(InterpreterObject):
      def __init__(self, res):
          super().__init__()
          self.res = res
          self.methods.update({'returncode': self.returncode_method,
                               'compiled': self.compiled_method,
                               'stdout': self.stdout_method,
                               'stderr': self.stderr_method,
                               })
  
      @noPosargs
      @permittedKwargs({})
      def returncode_method(self, args, kwargs):
          return self.res.returncode
  
      @noPosargs
      @permittedKwargs({})
      def compiled_method(self, args, kwargs):
          return self.res.compiled
  
      @noPosargs
      @permittedKwargs({})
      def stdout_method(self, args, kwargs):
          return self.res.stdout
  
      @noPosargs
      @permittedKwargs({})
      def stderr_method(self, args, kwargs):
          return self.res.stderr
  
  class RunProcess(InterpreterObject):
  
      def __init__(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False, check=False, capture=True):
          super().__init__()
          if not isinstance(cmd, ExternalProgram):
              raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
          self.capture = capture
          pc, self.stdout, self.stderr = self.run_command(cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check)
          self.returncode = pc.returncode
          self.methods.update({'returncode': self.returncode_method,
                               'stdout': self.stdout_method,
                               'stderr': self.stderr_method,
                               })
  
      def run_command(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check=False):
          command_array = cmd.get_command() + args
          env = {'MESON_SOURCE_ROOT': source_dir,
                 'MESON_BUILD_ROOT': build_dir,
                 'MESON_SUBDIR': subdir,
                 'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in mesonintrospect]),
                 }
          if in_builddir:
              cwd = os.path.join(build_dir, subdir)
          else:
              cwd = os.path.join(source_dir, subdir)
          child_env = os.environ.copy()
          child_env.update(env)
          stdout = subprocess.PIPE if self.capture else subprocess.DEVNULL
          mlog.debug('Running command:', ' '.join(command_array))
          try:
              p, o, e = Popen_safe(command_array, stdout=stdout, env=child_env, cwd=cwd)
              if self.capture:
                  mlog.debug('--- stdout ---')
                  mlog.debug(o)
              else:
                  o = ''
                  mlog.debug('--- stdout disabled ---')
              mlog.debug('--- stderr ---')
              mlog.debug(e)
              mlog.debug('')
  
              if check and p.returncode != 0:
                  raise InterpreterException('Command "{}" failed with status {}.'.format(' '.join(command_array), p.returncode))
  
              return p, o, e
          except FileNotFoundError:
              raise InterpreterException('Could not execute command "%s".' % ' '.join(command_array))
  
      @noPosargs
      @permittedKwargs({})
      def returncode_method(self, args, kwargs):
          return self.returncode
  
      @noPosargs
      @permittedKwargs({})
      def stdout_method(self, args, kwargs):
          return self.stdout
  
      @noPosargs
      @permittedKwargs({})
      def stderr_method(self, args, kwargs):
          return self.stderr
  
  class ConfigureFileHolder(InterpreterObject, ObjectHolder):
  
      def __init__(self, subdir, sourcename, targetname, configuration_data):
          InterpreterObject.__init__(self)
          ObjectHolder.__init__(self, build.ConfigureFile(subdir, sourcename,
                                                          targetname, configuration_data))
  
  
  class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder):
      def __init__(self):
          MutableInterpreterObject.__init__(self)
          ObjectHolder.__init__(self, build.EnvironmentVariables())
          self.methods.update({'set': self.set_method,
                               'append': self.append_method,
                               'prepend': self.prepend_method,
                               })
  
      def __repr__(self):
          repr_str = "<{0}: {1}>"
          return repr_str.format(self.__class__.__name__, self.held_object.envvars)
  
      def add_var(self, method, args, kwargs):
          if not isinstance(kwargs.get("separator", ""), str):
              raise InterpreterException("EnvironmentVariablesHolder methods 'separator'"
                                         " argument needs to be a string.")
          if len(args) < 2:
              raise InterpreterException("EnvironmentVariablesHolder methods require at least"
                                         "2 arguments, first is the name of the variable and"
                                         " following one are values")
          self.held_object.envvars.append((method, args[0], args[1:], kwargs))
  
      @stringArgs
      @permittedKwargs({'separator'})
      def set_method(self, args, kwargs):
          self.add_var(self.held_object.set, args, kwargs)
  
      @stringArgs
      @permittedKwargs({'separator'})
      def append_method(self, args, kwargs):
          self.add_var(self.held_object.append, args, kwargs)
  
      @stringArgs
      @permittedKwargs({'separator'})
      def prepend_method(self, args, kwargs):
          self.add_var(self.held_object.prepend, args, kwargs)
  
  
  class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder):
      def __init__(self):
          MutableInterpreterObject.__init__(self)
          self.used = False # These objects become immutable after use in configure_file.
          ObjectHolder.__init__(self, build.ConfigurationData())
          self.methods.update({'set': self.set_method,
                               'set10': self.set10_method,
                               'set_quoted': self.set_quoted_method,
                               'has': self.has_method,
                               'get': self.get_method,
                               'get_unquoted': self.get_unquoted_method,
                               'merge_from': self.merge_from_method,
                               })
  
      def is_used(self):
          return self.used
  
      def mark_used(self):
          self.used = True
  
      def validate_args(self, args, kwargs):
          if len(args) == 1 and isinstance(args[0], list) and len(args[0]) == 2:
              mlog.log(mlog.red('DEPRECATION:'),
                       '''Passing a list as the single argument to configuration_data.set is deprecated.
  This will become a hard error in the future''')
              args = args[0]
  
          if len(args) != 2:
              raise InterpreterException("Configuration set requires 2 arguments.")
          if self.used:
              raise InterpreterException("Can not set values on configuration object that has been used.")
          name = args[0]
          val = args[1]
          desc = kwargs.get('description', None)
          if not isinstance(name, str):
              raise InterpreterException("First argument to set must be a string.")
          if desc is not None and not isinstance(desc, str):
              raise InterpreterException('Description must be a string.')
  
          return name, val, desc
  
      @noArgsFlattening
      def set_method(self, args, kwargs):
          (name, val, desc) = self.validate_args(args, kwargs)
          self.held_object.values[name] = (val, desc)
  
      def set_quoted_method(self, args, kwargs):
          (name, val, desc) = self.validate_args(args, kwargs)
          if not isinstance(val, str):
              raise InterpreterException("Second argument to set_quoted must be a string.")
          escaped_val = '\\"'.join(val.split('"'))
          self.held_object.values[name] = ('"' + escaped_val + '"', desc)
  
      def set10_method(self, args, kwargs):
          (name, val, desc) = self.validate_args(args, kwargs)
          if val:
              self.held_object.values[name] = (1, desc)
          else:
              self.held_object.values[name] = (0, desc)
  
      def has_method(self, args, kwargs):
          return args[0] in self.held_object.values
  
      @FeatureNew('configuration_data.get()', '0.38.0')
      @noArgsFlattening
      def get_method(self, args, kwargs):
          if len(args) < 1 or len(args) > 2:
              raise InterpreterException('Get method takes one or two arguments.')
          name = args[0]
          if name in self.held_object:
              return self.held_object.get(name)[0]
          if len(args) > 1:
              return args[1]
          raise InterpreterException('Entry %s not in configuration data.' % name)
  
      @FeatureNew('get_unquoted', '0.44.0')
      def get_unquoted_method(self, args, kwargs):
          if len(args) < 1 or len(args) > 2:
              raise InterpreterException('Get method takes one or two arguments.')
          name = args[0]
          if name in self.held_object:
              val = self.held_object.get(name)[0]
          elif len(args) > 1:
              val = args[1]
          else:
              raise InterpreterException('Entry %s not in configuration data.' % name)
          if val[0] == '"' and val[-1] == '"':
              return val[1:-1]
          return val
  
      def get(self, name):
          return self.held_object.values[name] # (val, desc)
  
      def keys(self):
          return self.held_object.values.keys()
  
      def merge_from_method(self, args, kwargs):
          if len(args) != 1:
              raise InterpreterException('Merge_from takes one positional argument.')
          from_object = args[0]
          if not isinstance(from_object, ConfigurationDataHolder):
              raise InterpreterException('Merge_from argument must be a configuration data object.')
          from_object = from_object.held_object
          for k, v in from_object.values.items():
              self.held_object.values[k] = v
  
  # Interpreter objects can not be pickled so we must have
  # these wrappers.
  
  class DependencyHolder(InterpreterObject, ObjectHolder):
      def __init__(self, dep):
          InterpreterObject.__init__(self)
          ObjectHolder.__init__(self, dep)
          self.methods.update({'found': self.found_method,
                               'type_name': self.type_name_method,
                               'version': self.version_method,
                               'get_pkgconfig_variable': self.pkgconfig_method,
                               'get_configtool_variable': self.configtool_method,
                               'partial_dependency': self.partial_dependency_method,
                               })
  
      @noPosargs
      @permittedKwargs({})
      def type_name_method(self, args, kwargs):
          return self.held_object.type_name
  
      @noPosargs
      @permittedKwargs({})
      def found_method(self, args, kwargs):
          if self.held_object.type_name == 'internal':
              return True
          return self.held_object.found()
  
      @noPosargs
      @permittedKwargs({})
      def version_method(self, args, kwargs):
          return self.held_object.get_version()
  
      @permittedKwargs({'define_variable'})
      def pkgconfig_method(self, args, kwargs):
          args = listify(args)
          if len(args) != 1:
              raise InterpreterException('get_pkgconfig_variable takes exactly one argument.')
          varname = args[0]
          if not isinstance(varname, str):
              raise InterpreterException('Variable name must be a string.')
          return self.held_object.get_pkgconfig_variable(varname, kwargs)
  
      @FeatureNew('get_configtool_variable', '0.44.0')
      @permittedKwargs({})
      def configtool_method(self, args, kwargs):
          args = listify(args)
          if len(args) != 1:
              raise InterpreterException('get_configtool_variable takes exactly one argument.')
          varname = args[0]
          if not isinstance(varname, str):
              raise InterpreterException('Variable name must be a string.')
          return self.held_object.get_configtool_variable(varname)
  
      @FeatureNew('dep.partial_dependency', '0.46.0')
      @noPosargs
      @permittedKwargs(permitted_method_kwargs['partial_dependency'])
      def partial_dependency_method(self, args, kwargs):
          return DependencyHolder(self.held_object.get_partial_dependency(**kwargs))
  
  class InternalDependencyHolder(InterpreterObject, ObjectHolder):
      def __init__(self, dep):
          InterpreterObject.__init__(self)
          ObjectHolder.__init__(self, dep)
          self.methods.update({'found': self.found_method,
                               'version': self.version_method,
                               'partial_dependency': self.partial_dependency_method,
                               })
  
      @noPosargs
      @permittedKwargs({})
      def found_method(self, args, kwargs):
          return True
  
      @noPosargs
      @permittedKwargs({})
      def version_method(self, args, kwargs):
          return self.held_object.get_version()
  
      @FeatureNew('dep.partial_dependency', '0.46.0')
      @noPosargs
      @permittedKwargs(permitted_method_kwargs['partial_dependency'])
      def partial_dependency_method(self, args, kwargs):
          return DependencyHolder(self.held_object.get_partial_dependency(**kwargs))
  
  class ExternalProgramHolder(InterpreterObject, ObjectHolder):
      def __init__(self,
  
  [... the rest is omitted ...]
files: mesonbuild/interpreter.py