Esempio n. 1
0
    def __LoadGroup(self,
                    module_directory,
                    parent_group,
                    module_path=None,
                    allow_non_existing_modules=False,
                    exception_if_present=None,
                    top_group=None):
        """Loads a single command group from a directory.

    Args:
      module_directory: The path to the location of the module.
      parent_group: backend.CommandGroup, The parent command group for this
        command group, or None if this is the top group.
      module_path: An optional name override for the module. If not set, it will
        default to using the name of the directory containing the module.
      allow_non_existing_modules: True to allow this module directory to not
        exist, False to raise an exception if this module does not exist.
      exception_if_present: Exception, An exception to throw if the module
        actually exists, or None.
      top_group: backend.CommandGroup, The top command group for this CLI.

    Raises:
      LayoutException: If the module directory does not exist and
      allow_non_existing is False.

    Returns:
      The backend.CommandGroup object, or None if the module directory does not
      exist and allow_non_existing is True.
    """
        if not os.path.isdir(module_directory):
            if allow_non_existing_modules:
                return None
            raise backend.LayoutException(
                'The given module directory does not exist: {}'.format(
                    module_directory))
        elif exception_if_present:
            # pylint: disable=raising-bad-type, This will be an actual exception.
            raise exception_if_present

        module_root, module = os.path.split(module_directory)
        if not module_path:
            module_path = [module]
        # If this is the top level, don't register the name of the module directory
        # itself, it should assume the name of the command.  If this is another
        # module directory, its name gets explicitly registered under the root
        # command.
        is_top = not parent_group
        sub_parser = parent_group.SubParser() if parent_group else None
        path = [self.__name] if is_top else [self.__name] + module_path
        group = backend.CommandGroup(module_root, [module],
                                     path,
                                     uuid.uuid4().hex,
                                     self,
                                     sub_parser,
                                     self.__config_hooks,
                                     help_func=self.__help_func,
                                     parent_group=top_group)

        return group
Esempio n. 2
0
    def __LoadTopGroup(self, group_info):
        """Actually loads the top group of the CLI based on the given group_info.

    Args:
      group_info: A tuple of (module_dir, module_path, name) generated by
        self.__GetGroupInfo()

    Returns:
      The backend.CommandGroup object.
    """
        (module_root, module, name, release_track) = group_info
        return backend.CommandGroup(module_root, module, [name], release_track,
                                    uuid.uuid4().hex, self, None)
Esempio n. 3
0
  def __LoadTopGroup(self, group_info):
    """Actually loads the top group of the CLI based on the given group_info.

    Args:
      group_info: A tuple of (module_dir, module_path, path) generated by
        self.__GetGroupInfo()

    Returns:
      The backend.CommandGroup object.
    """
    (module_root, module, path) = group_info
    return backend.CommandGroup(
        module_root, module, path, uuid.uuid4().hex, self, None,
        self.__config_hooks, help_func=self.__help_func)
Esempio n. 4
0
    def Generate(self):
        """Uses the registered information to generate the CLI tool.

    Returns:
      CLI, The generated CLI tool.
    """
        # The root group of the CLI.
        impl_path = self.__ValidateCommandOrGroupInfo(
            self.__command_root_directory, allow_non_existing_modules=False)
        top_group = backend.CommandGroup([impl_path], [self.__name],
                                         calliope_base.ReleaseTrack.GA,
                                         uuid.uuid4().hex, self, None)
        self.__AddBuiltinGlobalFlags(top_group)

        # Sub groups for each alternate release track.
        loaded_release_tracks = dict([(calliope_base.ReleaseTrack.GA,
                                       top_group)])
        track_names = set(track.prefix
                          for track in self.__release_tracks.keys())
        for track, (module_dir,
                    component) in self.__release_tracks.iteritems():
            impl_path = self.__ValidateCommandOrGroupInfo(
                module_dir,
                allow_non_existing_modules=self.__allow_non_existing_modules)
            if impl_path:
                # Add the release track sub group into the top group.
                # pylint: disable=protected-access
                top_group._groups_to_load[track.prefix] = [impl_path]
                # Override the release track because this is specifically a top level
                # release track group.
                track_group = top_group.LoadSubElement(
                    track.prefix,
                    allow_empty=True,
                    release_track_override=track)
                # Copy all the root elements of the top group into the release group.
                top_group.CopyAllSubElementsTo(track_group, ignore=track_names)
                loaded_release_tracks[track] = track_group
            elif component:
                self.__missing_components[track.prefix] = component

        # Load the normal set of registered sub groups.
        for module_dot_path, module_dir_path, component in self.__modules:
            is_command = module_dir_path.endswith(_COMMAND_SUFFIX)
            if is_command:
                module_dir_path = module_dir_path[:-len(_COMMAND_SUFFIX)]
            match = CLILoader.PATH_RE.match(module_dot_path)
            root, name = match.group(1, 2)
            try:
                # Mount each registered sub group under each release track that exists.
                for track, track_root_group in loaded_release_tracks.iteritems(
                ):
                    parent_group = self.__FindParentGroup(
                        track_root_group, root)
                    exception_if_present = None
                    if not parent_group:
                        if track != calliope_base.ReleaseTrack.GA:
                            # Don't error mounting sub groups if the parent group can't be
                            # found unless this is for the GA group.  The GA should always be
                            # there, but for alternate release channels, the parent group
                            # might not be enabled for that particular release channel, so it
                            # is valid to not exist.
                            continue
                        exception_if_present = command_loading.LayoutException(
                            'Root [{root}] for command group [{group}] does not exist.'
                            .format(root=root, group=name))

                    cmd_or_grp_name = module_dot_path.split('.')[-1]
                    impl_path = self.__ValidateCommandOrGroupInfo(
                        module_dir_path,
                        allow_non_existing_modules=self.
                        __allow_non_existing_modules,
                        exception_if_present=exception_if_present)

                    if impl_path:
                        # pylint: disable=protected-access
                        if is_command:
                            parent_group._commands_to_load[cmd_or_grp_name] = [
                                impl_path
                            ]
                        else:
                            parent_group._groups_to_load[cmd_or_grp_name] = [
                                impl_path
                            ]
                    elif component:
                        prefix = track.prefix + '.' if track.prefix else ''
                        self.__missing_components[prefix +
                                                  module_dot_path] = component
            except command_loading.CommandLoadFailure as e:
                log.exception(e)

        cli = self.__MakeCLI(top_group)

        return cli