def _CreateContext(cls, metadata, status_stream):
        jinja2_context = {}

        # Load the custom context defined in code
        for context_code in metadata["jinja2_context_code"]:
            dirname, basename = os.path.split(context_code)
            basename = os.path.splitext(basename)[0]

            sys.path.insert(0, dirname)
            with CallOnExit(lambda: sys.path.pop(0)):
                mod = importlib.import_module(basename)

            var = getattr(mod, context_code.var_name)
            del mod

            if isinstance(var, dict):
                for k, v in six.iteritems(var):
                    jinja2_context[k] = v
            else:
                jinja2_context[context_code.var_name] = var

        del metadata["jinja2_context_code"]

        # Load the custom context
        for k, v in six.iteritems(metadata["jinja2_context"]):
            if len(v) == 1:
                jinja2_context[k] = v[0]
            else:
                jinja2_context[k] = v

        metadata["jinja2_context"] = jinja2_context

        # Calculate the hashes of the input filenames. We will use this information
        # during comparison to determine if an input file has changed. It appears
        # that this value isn't used, but it is actually used when comparing the
        # context of two different invocations.

        # ----------------------------------------------------------------------
        def CalculateHash(input_filename):
            with open(input_filename, "rb") as f:
                return hashlib.sha256(f.read()).digest()

        # ----------------------------------------------------------------------

        metadata["hashes"] = [
            CalculateHash(input_filename)
            for input_filename in metadata["inputs"]
        ]

        # Get the output filenames
        if not metadata["preserve_dir_structure"]:
            # ----------------------------------------------------------------------
            def GetBaseDir(input_filename):
                return ''

            # ----------------------------------------------------------------------

        else:
            if len(metadata["inputs"]) == 1:
                common_prefix = os.path.dirname(metadata["inputs"][0])
            else:
                common_prefix = FileSystem.GetCommonPath(*metadata["inputs"])

            # ----------------------------------------------------------------------
            def GetBaseDir(input_filename):
                return FileSystem.TrimPath(input_filename, common_prefix)

            # ----------------------------------------------------------------------

        output_filenames = []

        for input_filename in metadata["inputs"]:
            output_filenames.append(
                os.path.join(
                    metadata["output_dir"],
                    GetBaseDir(input_filename),
                    '.'.join([
                        part
                        for part in os.path.basename(input_filename).split(".")
                        if part != "jinja2"
                    ]),
                ), )

        metadata["output_filenames"] = output_filenames

        return super(CodeGenerator,
                     cls)._CreateContext(metadata, status_stream)
    def Generate(
        simple_schema_generator,
        invoke_reason,
        input_filenames,
        output_filenames,
        name,
        elements,
        include_indexes,
        status_stream,
        verbose_stream,
        verbose,
        no_attributes,
    ):
        assert len(output_filenames) == 1, output_filenames
        output_filename = output_filenames[0]

        common_input_prefix = FileSystem.GetCommonPath(*input_filenames)

        with open(output_filename, "w") as f:
            f.write(
                textwrap.dedent(
                    """\
                    digraph g {
                        graph [
                            rankdir = "LR"
                        ];
                    """, ), )

            indented_stream = StreamDecorator(
                f,
                line_prefix="    ",
            )

            # ----------------------------------------------------------------------
            def Impl(element):
                if element.IsDefinitionOnly:
                    element_type = "Definition"
                    style = "dashed"
                elif getattr(element, "IsAttribute", False):
                    element_type = "Attribute"
                    style = "rounded"
                else:
                    element_type = "Standard"
                    style = None

                type_info_type = element.TypeInfo.__class__.__name__

                indented_stream.write(
                    textwrap.dedent(
                        """\
                        "{dotted}" [
                            shape = rectangle
                            {style}
                            label = <
                              <table border="0">
                                <tr>
                                  <td align="left"><b>{name}</b></td>
                                  <td align="right">{element_type}<br align="right"/>{type_info}</td>
                                </tr>
                                <hr/>
                                <tr>
                                  <td colspan="2">{source} [{line}:{column}]</td>
                                </tr>
                                <hr/>
                                <tr>
                                  <td align="left">Arity:</td>
                                  <td align="right">{arity}</td>
                                </tr>
                        """, ).format(
                            dotted=element.DottedName,
                            name=element.Name,
                            style="style = {}".format(style) if style else "",
                            element_type=element_type,
                            type_info=type_info_type,
                            source=FileSystem.TrimPath(element.Source,
                                                       common_input_prefix),
                            line=element.Line,
                            column=element.Column,
                            arity=element.TypeInfo.Arity.ToString() or "1",
                        ), )

                if type_info_type != "ClassTypeInfo":
                    indented_stream.write(
                        StringHelpers.LeftJustify(
                            textwrap.dedent(
                                """\
                                <tr>
                                  <td align="left">Constraints:</td>
                                  <td align="right">{}</td>
                                </tr>
                                """, ).format(
                                    html.escape(
                                        element.TypeInfo.ConstraintsDesc), ),
                            8,
                            skip_first_line=False,
                        ), )

                if not no_attributes:
                    table_rows = []

                    for key, metadata_value in six.iteritems(
                            element.Metadata.Values):
                        table_rows.append(
                            textwrap.dedent(
                                """\
                                <tr>
                                  <td align="left">{}:</td>
                                  <td align="right">{}</td>
                                </tr>
                                """, ).format(
                                    html.escape(key),
                                    html.escape(metadata_value.Value),
                                ), )

                    if table_rows:
                        indented_stream.write(
                            StringHelpers.LeftJustify(
                                textwrap.dedent(
                                    """\
                                    <hr/>
                                    {}
                                    """, ).format("".join(table_rows)),
                                8,
                                skip_first_line=False,
                            ), )

                indented_stream.write(
                    textwrap.dedent(
                        """\
                              </table>
                            >
                        ];
                        """, ), )

                for child in getattr(element, "Children", []):
                    Impl(child)
                    indented_stream.write('"{}":f0 -> "{}":f0\n'.format(
                        element.DottedName, child.DottedName))

            # ----------------------------------------------------------------------

            for element in elements:
                Impl(element)

            f.write("}\n")
def EntryPoint(
    root_dir,
    output_stream=sys.stdout,
):
    with StreamDecorator(output_stream).DoneManager(
            line_prefix='',
            prefix="\nResults: ",
            suffix='\n',
    ) as dm:
        repositories = []

        dm.stream.write(
            "\nSearching for repositories in '{}'...".format(root_dir))
        with dm.stream.DoneManager(done_suffix=lambda: inflect.no(
                "repository", len(repositories)), ):
            for scm, directory in EnumSCMs(root_dir):
                if scm.Name != "Mercurial":
                    continue

                repositories.append(directory)

        # Organize the repos
        dm.stream.write("Organizing...")
        with dm.stream.DoneManager():
            repo_dict = OrderedDict()

            common_prefix = FileSystem.GetCommonPath(*repositories)
            common_prefix_len = len(common_prefix)

            for repository in repositories:
                suffix = repository[common_prefix_len:]

                parts = suffix.split(os.path.sep)

                repo_name = parts[-1]
                prefixes = parts[:-1]

                rd = repo_dict
                for prefix in prefixes:
                    rd.setdefault(prefix, OrderedDict())
                    rd = rd[prefix]

                rd[repo_name] = repository

        # Write the content
        dm.stream.write("Writing TortoiseHg content...")
        with dm.stream.DoneManager():
            filename = os.path.join(os.getenv("APPDATA"), "TortoiseHg",
                                    "thg-reporegistry.xml")
            assert os.path.isfile(filename), filename

            with open(filename, 'w') as f:
                # ----------------------------------------------------------------------
                def GenerateContent(root, is_root):
                    items = []

                    for k, v in six.iteritems(root):
                        if isinstance(v, six.string_types):
                            items.append(
                                '<repo root="{}" shortname="{}" />\n'.format(
                                    v,
                                    os.path.basename(k),
                                ))
                        else:
                            tag_name = "allgroup" if is_root else "group"

                            items.append(
                                textwrap.dedent("""\
                                <{tag_name} name="{name}">
                                  {content}
                                </{tag_name}>
                                """).format(
                                    tag_name=tag_name,
                                    name=k,
                                    content=StringHelpers.LeftJustify(
                                        GenerateContent(v, False), 2).rstrip(),
                                ))

                    return ''.join(items)

                # ----------------------------------------------------------------------

                f.write(
                    textwrap.dedent("""\
                    <?xml version="1.0" encoding="UTF-8"?>
                    <reporegistry>
                      <treeitem>
                    {}
                      </treeitem>
                    </reporegistry>
                    """).format(
                        StringHelpers.LeftJustify(
                            GenerateContent(repo_dict, True).rstrip(),
                            4,
                            skip_first_line=False,
                        )))
        return dm.result
Пример #4
0
def _RedirectEntryPoint(function_name, entry_point, config):
    assert function_name
    assert entry_point
    assert config

    # <Use of exec> pylint: disable = W0122
    # <Use of eval> pylint: disable = W0123

    required_arguments = []

    if config.Configurations:
        if function_name != "Clean" or config.ConfigurationRequiredOnClean:
            assert "configuration" in entry_point.ConstraintsDecorator.Preconditions, function_name
            entry_point.ConstraintsDecorator.Preconditions["configuration"] = CommandLine.EnumTypeInfo(config.Configurations)

            required_arguments.append("configuration")

    if config.RequiresOutputDir:
        required_arguments.append("output_dir")

    num_required_args = six.get_function_code(entry_point.Function).co_argcount - len(list(six.get_function_defaults(entry_point.Function) or []))
    arguments = six.get_function_code(entry_point.Function).co_varnames[:num_required_args]

    if required_arguments and list(arguments[:len(required_arguments) + 1]) != required_arguments:
        raise Exception("The entry point '{}' should begin with the arguments '{}' ('{}' were found)".format( function_name,
                                                                                                              ', '.join(required_arguments),
                                                                                                              ', '.join(arguments),
                                                                                                            ))

    # Dynamically redefine the function so that it prints information that lets the user know the the
    # functionality can't be executed on the current platform/configuration/environment.
    if config.RequiredDevelopmentEnvironment and config.RequiredDevelopmentEnvironment.lower() not in [ CurrentShell.Name.lower(),
                                                                                                        CurrentShell.CategoryName.lower(),
                                                                                                      ]:
        exec(textwrap.dedent(
            """\
            def {name}({args}):
                sys.stdout.write("\\nINFO: This can only be run on '{env}'.\\n")
                return 0
            """).format( name=function_name,
                         args=', '.join(arguments),
                         env=config.RequiredDevelopmentEnvironment,
                       ))

        entry_point.Function = eval(function_name)

    elif config.RequiredDevelopmentConfigurations and not _RedirectEntryPoint_IsSupportedDevelopmentConfiguration(config.RequiredDevelopmentConfigurations):
        exec(textwrap.dedent(
            """\
            def {name}({args}):
                sys.stdout.write("\\nINFO: This can only be run in development environments activated with the configurations {configs}.\\n")
                return 0
            """).format( name=function_name,
                         args=', '.join(arguments),
                         configs=', '.join([ "'{}'".format(configuration) for configuration in config.RequiredDevelopmentConfigurations ]),
                       ))

        entry_point.Function = eval(function_name)

    elif config.DisableIfDependencyEnvironment:
        repo_path = os.getenv(RepositoryBootstrapConstants.DE_REPO_ROOT_NAME)

        if FileSystem.GetCommonPath(repo_path, inspect.getfile(entry_point.Function)).rstrip(os.path.sep) != repo_path:
            exec(textwrap.dedent(
                """\
                def {name}({args}):
                    sys.stdout.write("\\nINFO: This module is not build when invoked as a dependency.\\n")
                    return 0
                """).format( name=function_name,
                             args=', '.join(arguments),
                           ))

            entry_point.Function = eval(function_name)