def test_indented_repr(self): data = textwrap.dedent(r''' { 'a': 1, 'b': b'abc', b'c': 'xyz', 'd': False, 'e': { 'a': 1, 'b': b'2', 'c': '3', }, 'f': [ 1, b'2', '3', ], 'pile_of_bytes': b'\xf0\x9f\x92\xa9', 'pile_of_poo': '💩', 'special_chars': '\\\'"\x08\n\t', 'with_accents': 'éà ñ', }''').lstrip() obj = eval(data) self.assertEqual(indented_repr(obj), data)
def config_status(config): # Sanitize config data to feed config.status # Ideally, all the backend and frontend code would handle the booleans, but # there are so many things involved, that it's easier to keep config.status # untouched for now. def sanitized_bools(v): if v is True: return '1' if v is False: return '' return v sanitized_config = {} sanitized_config['substs'] = { k: sanitized_bools(v) for k, v in config.iteritems() if k not in ('DEFINES', 'non_global_defines', 'TOPSRCDIR', 'TOPOBJDIR', 'CONFIG_STATUS_DEPS') } sanitized_config['defines'] = { k: sanitized_bools(v) for k, v in config['DEFINES'].iteritems() } sanitized_config['non_global_defines'] = config['non_global_defines'] sanitized_config['topsrcdir'] = config['TOPSRCDIR'] sanitized_config['topobjdir'] = config['TOPOBJDIR'] sanitized_config['mozconfig'] = config.get('MOZCONFIG') # Create config.status. Eventually, we'll want to just do the work it does # here, when we're able to skip configure tests/use cached results/not rely # on autoconf. logging.getLogger('moz.configure').info('Creating config.status') encoding = 'mbcs' if sys.platform == 'win32' else 'utf-8' with codecs.open('config.status', 'w', encoding) as fh: fh.write(textwrap.dedent('''\ #!%(python)s # coding=%(encoding)s from __future__ import unicode_literals from mozbuild.util import encode encoding = '%(encoding)s' ''') % {'python': config['PYTHON'], 'encoding': encoding}) # A lot of the build backend code is currently expecting byte # strings and breaks in subtle ways with unicode strings. (bug 1296508) for k, v in sanitized_config.iteritems(): fh.write('%s = encode(%s, encoding)\n' % (k, indented_repr(v))) fh.write("__all__ = ['topobjdir', 'topsrcdir', 'defines', " "'non_global_defines', 'substs', 'mozconfig']") if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'): fh.write(textwrap.dedent(''' if __name__ == '__main__': from mozbuild.util import patch_main patch_main() from mozbuild.config_status import config_status args = dict([(name, globals()[name]) for name in __all__]) config_status(**args) ''')) partial_config = PartialConfigEnvironment(config['TOPOBJDIR']) partial_config.write_vars(sanitized_config) # Write out a file so the build backend knows to re-run configure when # relevant Python changes. with open('config_status_deps.in', 'w') as fh: for f in itertools.chain(config['CONFIG_STATUS_DEPS'], iter_modules_in_path(config['TOPOBJDIR'], config['TOPSRCDIR'])): fh.write('%s\n' % mozpath.normpath(f)) # Other things than us are going to run this file, so we need to give it # executable permissions. os.chmod('config.status', 0o755) if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'): from mozbuild.config_status import config_status # Some values in sanitized_config also have more complex types, such as # EnumString, which using when calling config_status would currently # break the build, as well as making it inconsistent with re-running # config.status. Fortunately, EnumString derives from unicode, so it's # covered by converting unicode strings. # A lot of the build backend code is currently expecting byte strings # and breaks in subtle ways with unicode strings. return config_status(args=[], **encode(sanitized_config, encoding)) return 0
def config_status(config): # Sanitize config data to feed config.status # Ideally, all the backend and frontend code would handle the booleans, but # there are so many things involved, that it's easier to keep config.status # untouched for now. def sanitized_bools(v): if v is True: return '1' if v is False: return '' return v sanitized_config = {} sanitized_config['substs'] = { k: sanitized_bools(v) for k, v in six.iteritems(config) if k not in ('DEFINES', 'non_global_defines', 'TOPSRCDIR', 'TOPOBJDIR', 'CONFIG_STATUS_DEPS') } sanitized_config['defines'] = { k: sanitized_bools(v) for k, v in six.iteritems(config['DEFINES']) } sanitized_config['non_global_defines'] = config['non_global_defines'] sanitized_config['topsrcdir'] = config['TOPSRCDIR'] sanitized_config['topobjdir'] = config['TOPOBJDIR'] sanitized_config['mozconfig'] = config.get('MOZCONFIG') if not check_unicode(sanitized_config): print("Configuration should be all unicode.", file=sys.stderr) print("Please file a bug for the above.", file=sys.stderr) sys.exit(1) # Create config.status. Eventually, we'll want to just do the work it does # here, when we're able to skip configure tests/use cached results/not rely # on autoconf. logging.getLogger('moz.configure').info('Creating config.status') with codecs.open('config.status', 'w', 'utf-8') as fh: fh.write(textwrap.dedent('''\ #!%(python)s # coding=utf-8 from __future__ import unicode_literals ''') % {'python': config['PYTHON']}) for k, v in six.iteritems(sanitized_config): fh.write('%s = %s\n' % (k, indented_repr(v))) fh.write("__all__ = ['topobjdir', 'topsrcdir', 'defines', " "'non_global_defines', 'substs', 'mozconfig']") if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'): fh.write(textwrap.dedent(''' if __name__ == '__main__': from mozbuild.util import patch_main patch_main() from mozbuild.config_status import config_status args = dict([(name, globals()[name]) for name in __all__]) config_status(**args) ''')) partial_config = PartialConfigEnvironment(config['TOPOBJDIR']) partial_config.write_vars(sanitized_config) # Write out a file so the build backend knows to re-run configure when # relevant Python changes. with open('config_status_deps.in', 'w') as fh: for f in itertools.chain(config['CONFIG_STATUS_DEPS'], iter_modules_in_path(config['TOPOBJDIR'], config['TOPSRCDIR'])): fh.write('%s\n' % mozpath.normpath(f)) # Other things than us are going to run this file, so we need to give it # executable permissions. os.chmod('config.status', 0o755) if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'): from mozbuild.config_status import config_status # Some values in sanitized_config also have more complex types, such as # EnumString, which using when calling config_status would currently # break the build, as well as making it inconsistent with re-running # config.status, for which they are normalized to plain strings via # indented_repr. Likewise for non-dict non-string iterables being # converted to lists. def normalize(obj): if isinstance(obj, dict): return { k: normalize(v) for k, v in six.iteritems(obj) } if isinstance(obj, six.text_type): return six.text_type(obj) if isinstance(obj, Iterable): return [normalize(o) for o in obj] return obj return config_status(args=[], **normalize(sanitized_config)) return 0
def config_status(config): # Sanitize config data to feed config.status # Ideally, all the backend and frontend code would handle the booleans, but # there are so many things involved, that it's easier to keep config.status # untouched for now. def sanitized_bools(v): if v is True: return '1' if v is False: return '' return v sanitized_config = {} sanitized_config['substs'] = { k: sanitized_bools(v) for k, v in config.iteritems() if k not in ('DEFINES', 'non_global_defines', 'TOPSRCDIR', 'TOPOBJDIR', 'ALL_CONFIGURE_PATHS') } sanitized_config['defines'] = { k: sanitized_bools(v) for k, v in config['DEFINES'].iteritems() } sanitized_config['non_global_defines'] = config['non_global_defines'] sanitized_config['topsrcdir'] = config['TOPSRCDIR'] sanitized_config['topobjdir'] = config['TOPOBJDIR'] sanitized_config['mozconfig'] = config.get('MOZCONFIG') # Create config.status. Eventually, we'll want to just do the work it does # here, when we're able to skip configure tests/use cached results/not rely # on autoconf. print("Creating config.status", file=sys.stderr) encoding = 'mbcs' if sys.platform == 'win32' else 'utf-8' with codecs.open('config.status', 'w', encoding) as fh: fh.write( textwrap.dedent('''\ #!%(python)s # coding=%(encoding)s from __future__ import unicode_literals from mozbuild.util import encode encoding = '%(encoding)s' ''') % { 'python': config['PYTHON'], 'encoding': encoding }) # A lot of the build backend code is currently expecting byte # strings and breaks in subtle ways with unicode strings. (bug 1296508) for k, v in sanitized_config.iteritems(): fh.write('%s = encode(%s, encoding)\n' % (k, indented_repr(v))) fh.write("__all__ = ['topobjdir', 'topsrcdir', 'defines', " "'non_global_defines', 'substs', 'mozconfig']") if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'): fh.write( textwrap.dedent(''' if __name__ == '__main__': from mozbuild.util import patch_main patch_main() from mozbuild.config_status import config_status args = dict([(name, globals()[name]) for name in __all__]) config_status(**args) ''')) partial_config = PartialConfigEnvironment(config['TOPOBJDIR']) partial_config.write_vars(sanitized_config) # Write out a depfile so Make knows to re-run configure when relevant Python # changes. mk = Makefile() rule = mk.create_rule() rule.add_targets(["%s/config.status" % config['TOPOBJDIR']]) rule.add_dependencies( itertools.chain( config['ALL_CONFIGURE_PATHS'], iter_modules_in_path(config['TOPOBJDIR'], config['TOPSRCDIR']))) with open('configure.d', 'w') as fh: mk.dump(fh) # Other things than us are going to run this file, so we need to give it # executable permissions. os.chmod('config.status', 0o755) if config.get('MOZ_BUILD_APP') != 'js' or config.get('JS_STANDALONE'): from mozbuild.config_status import config_status # Some values in sanitized_config also have more complex types, such as # EnumString, which using when calling config_status would currently # break the build, as well as making it inconsistent with re-running # config.status. Fortunately, EnumString derives from unicode, so it's # covered by converting unicode strings. # A lot of the build backend code is currently expecting byte strings # and breaks in subtle ways with unicode strings. return config_status(args=[], **encode(sanitized_config, encoding)) return 0