Esempio n. 1
0
 def __init__(self, notifier=DEFAULT_NOTIFIER):
     self.home_dir = AbsolutePath(str(Path.home()))
     self.app_dir = AbsolutePath.join(self.home_dir, f".{self.app_name}").mkdir()
     self.dbs_dir = AbsolutePath.join(self.app_dir, "databases").mkdir()
     self.lang_dir = AbsolutePath.join(self.app_dir, "languages").mkdir()
     self.config_path = AbsolutePath.join(self.app_dir, "config.json")
     self.config = Config()
     self.databases = {}  # type: Dict[AbsolutePath, Optional[Database]]
     self.languages = {}  # type: Dict[AbsolutePath, Optional[DefaultLanguage]]
     self.notifier = notifier
     # Load database names.
     for entry in FileSystem.scandir(self.dbs_dir.path):  # type: os.DirEntry
         if entry.is_dir():
             self.databases[AbsolutePath(entry.path)] = None
     # Load language names.
     for entry in FileSystem.scandir(self.lang_dir.path):  # type: os.DirEntry
         path = AbsolutePath(entry.path)
         if path.isfile() and path.extension == "txt":
             self.languages[path] = None
     # Load default languages names.
     for entry in FileSystem.scandir(
         os.path.join(package_dir(), "language", "default")
     ):
         path = AbsolutePath(entry.path)
         if path.isfile() and path.extension == "txt":
             print("Checking embedded language", path.title)
             user_path = AbsolutePath.join(self.lang_dir, path.get_basename())
             if user_path in self.languages:
                 if user_path.get_date_modified() < path.get_date_modified():
                     user_path.delete()
                     path.copy_file_to(user_path)
                     print("Updated embedded language", path.title)
                 else:
                     print("User language more up-to-date", path.title)
             else:
                 path.copy_file_to(user_path)
                 self.languages[user_path] = None
                 print("Installed embedded language", path.title)
     # Load config file.
     if self.config_path.exists():
         assert self.config_path.isfile()
         self.config.update(parse_json(self.config_path))
     # Load language.
     lang_path = AbsolutePath.join(self.lang_dir, f"{self.config.language}.txt")
     if lang_path not in self.languages:
         if self.config.language == DefaultLanguage.__language__:
             print(
                 "[Default language]", DefaultLanguage.__language__, file=sys.stderr
             )
             dff_dump(language_to_dict(DefaultLanguage, extend=False), lang_path)
         else:
             raise exceptions.MissingLanguageFile(self.config.language)
     self.languages[lang_path] = self._load_lang(lang_path)
Esempio n. 2
0
 def list_files(self, output: str):
     self.database.list_files(output)
     output_path = AbsolutePath(output)
     if not output_path.isfile():
         raise OSError("Unable to output videos file names in %s" %
                       output_path)
     return str(output_path)
def main():
    if len(sys.argv) != 2:
        return
    path = AbsolutePath(sys.argv[1]).assert_file()
    assert path.extension.lower() == "webp"
    image = Image.open(path.path)
    image.info.pop("background", None)
    assert image.is_animated
    output_path = AbsolutePath.join(path.get_directory(), f"{path.title}.gif")
    image.save(output_path.path, "gif", save_all=True, optimize=False)
    print(output_path)
Esempio n. 4
0
    def __init__(self):
        self.app_name = "Pysaurus"
        self.home_dir = AbsolutePath(str(Path.home()))
        self.app_dir = AbsolutePath.join(self.home_dir,
                                         f".{self.app_name}").mkdir()
        self.db_path = AbsolutePath.join(self.app_dir, "databases.db")
        self.lang_dir = AbsolutePath.join(self.app_dir, "lang").mkdir()

        self.db = VideoDatabase(self.db_path.path)
        row = self.db.query_one("SELECT application_id, lang FROM application")
        self.application_id = row[0]
        self.lang = row[1]

        say.set_language(self.lang)
        say.set_folder(self.lang_dir)
Esempio n. 5
0
def _collect_videos_info(folder: str, files: Dict[AbsolutePath,
                                                  VideoRuntimeInfo]):
    entry: os.DirEntry
    for entry in FileSystem.scandir(folder):
        if entry.is_dir():
            _collect_videos_info(entry.path, files)
        elif (functions.get_file_extension(entry.name)
              in constants.VIDEO_SUPPORTED_EXTENSIONS):
            stat = entry.stat()
            files[AbsolutePath(entry.path)] = VideoRuntimeInfo(
                size=stat.st_size,
                mtime=stat.st_mtime,
                driver_id=stat.st_dev,
                is_file=True,
            )
Esempio n. 6
0
def main():
    if len(sys.argv) != 2:
        print("No path specified.")
        return
    folder = AbsolutePath(sys.argv[1]).assert_dir()
    lines = Counter()
    for file_name in folder.listdir():
        path = AbsolutePath.join(folder, file_name)
        if path.isfile():
            with open(path.path) as file:
                for line in file:
                    lines.update([line.strip()])
    inv = {}
    for line, count in lines.items():
        inv.setdefault(count, []).append(line)
    for count in sorted(inv, reverse=True):
        for line in sorted(inv[count]):
            print(f"{count}\t{line}")
Esempio n. 7
0
    def __load(self, folders: Optional[Iterable[PathType]] = None):
        to_save = False

        json_dict = self.__backup.load()
        if not isinstance(json_dict, dict):
            raise exceptions.InvalidDatabaseJSON(self.__backup.path)

        # Parsing settings.
        self.settings.update(json_dict.get("settings", {}))

        # Parsing date.
        if "date" in json_dict:
            self.date = DateModified(json_dict["date"])

        # Parsing folders.
        self.folders.update(AbsolutePath(path) for path in json_dict.get("folders", ()))
        if folders:
            lb = len(self.folders)
            self.folders.update(AbsolutePath.ensure(path) for path in folders)
            to_save = to_save or lb != len(self.folders)

        # Parsing video property types.
        for prop_dict in json_dict.get("prop_types", ()):
            self.add_prop_type(PropType.from_dict(prop_dict), save=False)

        # Parsing predictors
        self.predictors = json_dict.get("predictors", {})

        # Parsing videos.
        folders_tree = PathTree(self.folders)
        for video_dict in json_dict.get("videos", ()):
            if video_dict["U"]:
                video_state = VideoState.from_dict(video_dict)
            else:
                video_state = Video.from_dict(video_dict, database=self)
            video_state.discarded = not folders_tree.in_folders(video_state.filename)
            self.videos[video_state.filename] = video_state

        self.save(on_new_identifiers=to_save)
        self.__notifier.notify(notifications.DatabaseLoaded(self))
Esempio n. 8
0
def load_path_list_file(list_file_path):
    # type: (AbsolutePath) -> Iterable[AbsolutePath]
    return [AbsolutePath(string) for string in load_list_file(list_file_path)]
Esempio n. 9
0
from other.toolsaurus.functions import generate_temp_file_path
from other.toolsaurus.printable import to_column, to_table
from pysaurus.core import functions
from pysaurus.core.classes import StringPrinter
from pysaurus.core.components import AbsolutePath, Duration, FileSize
from pysaurus.core.modules import ImageUtils, VideoClipping
from pysaurus.database.video import Video
from pysaurus.database.video_features import VideoFeatures
from pysaurus.database.video_sorting import VideoSorting
from pysaurus.database.viewport.viewtools.search_def import SearchDef

TEST_LIST_FILE_PATH = AbsolutePath(
    os.path.join(
        pysaurus.application.utils.package_dir(),
        "../../../pysaurus",
        "..",
        ".local",
        ".local",
        "test_folder.log",
    ))


def path_in_directory(self: AbsolutePath, directory, is_case_insensitive=None):
    directory = AbsolutePath.ensure(directory)
    if not directory.isdir():
        return False
    directory = directory.standard_path
    path = self.standard_path
    if is_case_insensitive:
        directory = directory.lower()
        path = path.lower()
Esempio n. 10
0
 def get_filename(self):
     return AbsolutePath(self.__json__["filename"])
Esempio n. 11
0
    def ensure_miniatures(self, returns=False) -> Optional[List[Miniature]]:
        identifiers = set()  # type: Set[AbsolutePath]
        valid_dictionaries = []
        added_miniatures = []
        have_removed = False
        have_added = False

        if self.__miniatures_path.exists():
            with open(self.__miniatures_path.assert_file().path
                      ) as miniatures_file:
                json_array = json.load(miniatures_file)
            if not isinstance(json_array, list):
                raise exceptions.InvalidMiniaturesJSON(self.__miniatures_path)
            for dct in json_array:
                identifier = AbsolutePath(dct["i"])
                if identifier in self.videos and ImageUtils.DEFAULT_THUMBNAIL_SIZE == (
                        dct["w"],
                        dct["h"],
                ):
                    identifiers.add(identifier)
                    valid_dictionaries.append(dct)
            have_removed = len(valid_dictionaries) != len(json_array)
            del json_array

        available_videos = self.get_videos("readable", "with_thumbnails")
        tasks = [(video.filename, video.thumbnail_path)
                 for video in available_videos
                 if video.filename not in identifiers]

        job_notifier = job_notifications.CollectVideoMiniatures(
            len(tasks), self.notifier)
        if tasks:
            have_added = True
            jobs = functions.dispatch_tasks(tasks,
                                            CPU_COUNT,
                                            extra_args=[job_notifier])
            del tasks
            with Profiler(self.lang.profile_generate_miniatures,
                          self.notifier):
                results = functions.parallelize(
                    jobs_python.job_generate_miniatures, jobs, CPU_COUNT)
            del jobs
            for local_array in results:
                added_miniatures.extend(local_array)
            del results

        valid_miniatures = [Miniature.from_dict(d) for d in valid_dictionaries]
        available_miniatures = valid_miniatures + added_miniatures
        m_dict = {m.identifier: m
                  for m in available_miniatures}  # type: Dict[str, Miniature]

        m_no_groups = [
            m for m in valid_miniatures if not m.has_group_signature(
                self.settings.miniature_pixel_distance_radius,
                self.settings.miniature_group_min_size,
            )
        ] + added_miniatures
        if m_no_groups:
            group_computer = GroupComputer(
                group_min_size=self.settings.miniature_group_min_size,
                pixel_distance_radius=self.settings.
                miniature_pixel_distance_radius,
            )
            for dm in group_computer.batch_compute_groups(m_no_groups,
                                                          database=self):
                m_dict[dm.miniature_identifier].set_group_signature(
                    self.settings.miniature_pixel_distance_radius,
                    self.settings.miniature_group_min_size,
                    len(dm.pixel_groups),
                )

        if have_removed or have_added:
            with open(self.__miniatures_path.path, "w") as output_file:
                json.dump([m.to_dict() for m in available_miniatures],
                          output_file)

        self.notifier.notify(
            notifications.NbMiniatures(len(available_miniatures)))

        if returns:
            miniatures = []
            for video in available_videos:
                miniature = m_dict[video.filename.path]
                miniature.video_id = video.video_id
                miniatures.append(miniature)
            return miniatures
Esempio n. 12
0
 def modify(self, entry, indices: List, **kwargs):
     if not indices or not kwargs:
         return
     if entry == "video":
         if len(indices) > 1:
             for index in ("filename", "video_id"):
                 assert index not in kwargs
         video = None
         old = None
         for video_id in indices:
             video = self.__id_to_video[video_id]
             old = video.update(kwargs)
         if len(indices) == 1:
             if "filename" in old:
                 del self.videos[AbsolutePath(old["filename"])]
                 self.videos[video.filename] = video
             if "video_id" in old:
                 del self.__id_to_video[old["video_id"]]
                 self.__id_to_video[video.video_id] = video
     elif entry == "property":
         assert "definition" not in kwargs
         if len(indices) > 1:
             assert "name" not in kwargs
         prop_type = None
         old = None
         for prop_name in indices:
             prop_type = self.prop_types[prop_name]
             old = prop_type.update(kwargs)
         if len(indices) == 1 and "name" in old:
             del self.prop_types[old["name"]]
             self.prop_types[prop_type.name] = prop_type
             for video in self.videos.values():
                 if isinstance(video, Video) and old["name"] in video.properties:
                     video.properties[prop_type.name] = video.properties.pop(
                         old["name"]
                     )
         if "multiple" in old:
             if old["multiple"]:
                 # True -> False: converted to unique property
                 for prop_name in indices:
                     for video in self.videos.values():
                         if (
                             isinstance(video, Video)
                             and prop_name in video.properties
                         ):
                             if video.properties[prop_name]:
                                 video.properties[prop_name] = video.properties[
                                     prop_name
                                 ][0]
                             else:
                                 del video.properties[prop_name]
             else:
                 # False -> True: converted to multiple property
                 for prop_name in indices:
                     for video in self.videos.values():
                         if (
                             isinstance(video, Video)
                             and prop_name in video.properties
                         ):
                             video.properties[prop_name] = [
                                 video.properties[prop_name]
                             ]
     else:
         raise ValueError(f"Unknown database entry: {entry}")