def upload_single(self, filepath, test=False):

        self.modified = False

        google_cache = GoogleLibrary.cache()
        google_image_filenames = google_cache.get('image_filenames')

        filename = os.path.basename(filepath)
        if filename in google_image_filenames:
            logging.info(f"Image already uploaded: '{filename}'")
            return
        elif test:
            logging.info(f"Image NEEDS uploading: '{filename}'")
            return

        image_spec_list = [{'filepath': filepath, 'filename': filename}]
        creds = GoogleService.credentials()

        try:
            if not test:
                self.upload_image_spec_list(image_spec_list, creds)

        finally:
            if self.modified:
                GoogleLibrary.save_library()
    def upload_recursive(self, folder, recursive=True, test=False):

        logging.info(f"uploading images in folder: ({folder})")

        # Get only media types in the folder
        # image spec list holds a list of objects, sample below:
        # [
        #     {
        #         'filepath': ...,
        #         'filename': ...,
        #         'upload_token': ...
        #     },
        #     {
        #         .... next image object ....
        #     }
        # ]

        image_spec_list = []
        folder_items = os.listdir(folder)
        filenames = [
            f for f in folder_items
            if os.path.isfile(os.path.join(folder, f)) and self.is_media(f)
        ]

        google_cache = GoogleLibrary.cache()
        google_image_filenames = google_cache.get('image_filenames')

        for filename in filenames:

            # If image already in cache then ignore
            if filename in google_image_filenames:
                logging.info(f"Image already uploaded: '{filename}'")
                continue
            elif test:
                logging.info(f"Image needs upload: '{filename}'")
                continue

            # Build the spec for each file
            filepath = os.path.join(folder, filename)
            image_spec = {'filepath': filepath, 'filename': filename}
            image_spec_list.append(image_spec)

        if len(image_spec_list) <= 0:
            logging.info(f"NO IMAGES TO UPLOAD IN FOLDER '{folder}'")
        else:
            creds = GoogleService.credentials()
            self.upload_image_spec_list(image_spec_list, creds)

        # Traverse sub-folders if recursive is specified
        if not recursive:
            return
        dirnames = [
            d for d in folder_items if os.path.isdir(os.path.join(folder, d))
        ]
        for dirname in dirnames:
            self.upload_recursive(os.path.join(folder, dirname), recursive,
                                  test)