Esempio n. 1
0
    def test_write_indented_repr_py2(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)
        buf = io.StringIO()
        write_indented_repr(buf, obj)

        self.assertEqual(buf.getvalue(), data)
Esempio n. 2
0
def config_status(config, execute=True):
    # 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 sanitize_config(v):
        if v is True:
            return "1"
        if v is False:
            return ""
        # Serialize types that look like lists and tuples as lists.
        if not isinstance(v, (bytes, six.text_type, dict)) and isinstance(
                v, Iterable):
            return list(v)
        return v

    sanitized_config = {}
    sanitized_config["substs"] = {
        k: sanitize_config(v)
        for k, v in six.iteritems(config) if k not in (
            "DEFINES",
            "TOPSRCDIR",
            "TOPOBJDIR",
            "CONFIG_STATUS_DEPS",
            "OLD_CONFIGURE_SUBSTS",
            "OLD_CONFIGURE_DEFINES",
        )
    }
    for k, v in config["OLD_CONFIGURE_SUBSTS"]:
        sanitized_config["substs"][k] = sanitize_config(v)
    sanitized_config["defines"] = {
        k: sanitize_config(v)
        for k, v in six.iteritems(config["DEFINES"])
    }
    for k, v in config["OLD_CONFIGURE_DEFINES"]:
        sanitized_config["defines"][k] = sanitize_config(v)
    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)

    # 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

    sanitized_config = normalize(sanitized_config)

    # 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.
    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["PYTHON3"]})
        for k, v in sorted(six.iteritems(sanitized_config)):
            fh.write("%s = " % k)
            write_indented_repr(fh, v)
        fh.write("__all__ = ['topobjdir', 'topsrcdir', 'defines', "
                 "'substs', 'mozconfig']")

        if execute:
            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 io.open("config_status_deps.in", "w", encoding="utf-8",
                 newline="\n") as fh:
        for f in sorted(
                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 execute:
        from mozbuild.config_status import config_status

        return config_status(args=[], **sanitized_config)
    return 0
Esempio n. 3
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['PYTHON3']})
        for k, v in six.iteritems(sanitized_config):
            fh.write('%s = ' % k)
            write_indented_repr(fh, 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 io.open('config_status_deps.in', 'w', encoding='utf-8',
                 newline='\n') 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