def freeze(h, output_yaml, resolve, groups):
    """Output installed packages."""
    if not groups:
        groups = filter(lambda group: not group.lower().startswith("bower"),
                        h.requirements.keys())
    else:
        groups = [text_type.strip(group) for group in groups.split(",")]

    if output_yaml:
        for requirements in h.requirements.values():
            for requirement in requirements:
                if resolve and not requirement.version:
                    requirement.load_installed_version()
        click.echo(h.requirements.yaml)
    else:
        for group in groups:
            if not h.requirements[group]:
                continue
            click.echo("# {}".format(group))
            for requirement in h.requirements[group]:
                if resolve and not requirement.version:
                    requirement.load_installed_version()
                click.echo(str(requirement))
def parsed_error_msg(self):
        """
        Parse the error messages we receive from SoftwareSecure

        Error messages are written in the form:

            `[{"photoIdReasons": ["Not provided"]}]`

        Returns:
            str[]: List of error messages.
        """
        parsed_errors = []
        error_map = {
            'EdX name not provided': 'name_mismatch',
            'Name mismatch': 'name_mismatch',
            'Photo/ID Photo mismatch': 'photos_mismatched',
            'ID name not provided': 'id_image_missing_name',
            'Invalid Id': 'id_invalid',
            'No text': 'id_invalid',
            'Not provided': 'id_image_missing',
            'Photo hidden/No photo': 'id_image_not_clear',
            'Text not clear': 'id_image_not_clear',
            'Face out of view': 'user_image_not_clear',
            'Image not clear': 'user_image_not_clear',
            'Photo not provided': 'user_image_missing',
        }

        try:
            messages = set()
            message_groups = json.loads(self.error_msg)

            for message_group in message_groups:
                messages = messages.union(set(*six.itervalues(message_group)))

            for message in messages:
                parsed_error = error_map.get(message)

                if parsed_error:
                    parsed_errors.append(parsed_error)
                else:
                    log.debug(u'Ignoring photo verification error message: %s', message)
        except Exception:   # pylint: disable=broad-except
            log.exception(u'Failed to parse error message for SoftwareSecurePhotoVerification %d', self.pk)

        return parsed_errors