Source code for ooodev.conn.cache

# coding: utf-8
from __future__ import annotations
import os
from pathlib import Path
from shutil import copytree
import shutil
import tempfile
from typing import Tuple
from ooodev.utils.type_var import PathOrStr
from ooodev.utils import sys_info
from ooodev.cfg import config
from ooodev.io.log.named_logger import NamedLogger


[docs]class Cache: """Office Profile Cache Manager"""
[docs] def __init__(self, **kwargs) -> None: """ Cache Constructor Keyword Args: use_cache (bool, optional): Determines if caching is used. Default is True profile_path (PathOrStr, optional): Set the path used for getting LO profile data. If not set then an attempt is made to copy the user profiler. If set to empty string then no profile will be copied and a new profile will be created. If set to a path then that path will be used. Default is searched for in known locations. working_dir (PathOrStr, optional): sets the working dir to use. This is the dir that LO profile will be copied to. Defaults to a newly generated temp dir. no_shared_ext (bool, optional): Determines if shared extensions are used. If set to True then no shared extensions are disabled for the session. Default is False. """ self._log = NamedLogger(self.__class__.__name__) self._log.debug("Cache.__init__") self._use_cache = bool(kwargs.get("use_cache", True)) self._no_shared_ext = bool(kwargs.get("no_shared_ext", False)) self._profile_dir_name = "profile" self._no_share_dir_name = "no_share" self._profile_cached = False profile_path = kwargs.get("profile_path", None) if profile_path is None: # cache_path is now obsolete but kept for backwards compatibility profile_path = kwargs.get("cache_path", None) if profile_path is not None: self._log.warning("Cache.__init__(): cache_path is obsolete. Use profile_path instead.") if profile_path is not None: self.profile_path = profile_path working_dir = kwargs.get("working_dir", None) if working_dir is not None: self.working_dir = working_dir
def _get_profile_path(self) -> Path | None: # this method is only ever called the user does not provide a cache_path # see: https://www.howtogeek.com/289587/how-to-find-your-libreoffice-profile-folder-in-windows-macos-and-linux/ self._log.debug("Cache._get_profile_path()") cache_path = None platform = sys_info.SysInfo.get_platform() def get_path(ver: str) -> Tuple[bool, Path] | Tuple[bool, None]: # sourcery skip: merge-nested-ifs result = None if platform == sys_info.SysInfo.PlatformEnum.LINUX: result = Path("~/.config/libreoffice", ver).expanduser() elif platform == sys_info.SysInfo.PlatformEnum.WINDOWS: result = Path(os.getenv("APPDATA", ""), "LibreOffice", ver) elif platform == sys_info.SysInfo.PlatformEnum.MAC: result = Path("~/Library/Application Support/LibreOffice/", ver).expanduser() if result is not None: if result.exists() is False or result.is_dir() is False: result = None return (False, None) if result is None else (True, result) # lookup profile versions from config for s_ver in config.Config().profile_versions: # type: ignore is_valid, cache_path = get_path(s_ver) if is_valid: break self._log.debug(f"Cache._get_profile_path(): {cache_path}") return cache_path
[docs] def cache_profile(self) -> None: """ Copies user profile into cache path if it has not already been cached. Ignored if :py:attr:`~Cache.use_cache` is ``False`` """ # copy_cache_to_profile is called before this method if not self.use_cache: self._log.debug("Cache.cache_profile(): use_cache is False") return if not self.profile_path: self._log.debug("Cache.cache_profile(): cache_path is None") return if self._profile_cached is False: self._log.debug( f"Cache.cache_profile(): copying profile to cache. From: {self.user_profile} To: {self.profile_path}" ) copytree(self.user_profile, self.profile_path) return
[docs] def copy_cache_to_profile(self) -> None: """ Copies cached profile to profile dir set in :py:attr:`~.Cache.user_profile` Ignored if :py:attr:`~Cache.use_cache` is ``False`` """ # this method is called before cache_profile. if not self.use_cache: self._log.debug("Cache.copy_cache_to_profile(): use_cache is False") return if not self.profile_path: self._log.debug("Cache.copy_cache_to_profile(): cache_path is None") return if self.profile_path.exists() and self.profile_path.is_dir(): self._log.debug( f"Cache.copy_cache_to_profile(): copying cache to profile. From: {self.profile_path} To: {self.user_profile}" ) copytree(self.profile_path, self.user_profile) self._profile_cached = True else: # create the dir. # when when cache_profile is called it will cache # the profile into this dir. os.mkdir(self.user_profile) self._profile_cached = False
[docs] def del_working_dir(self): """ Deletes the current working directory of instance. Ignored if :py:attr:`~Cache.use_cache` is ``False`` """ if self.use_cache and (self.working_dir.exists() and self.working_dir.is_dir()): try: shutil.rmtree(self.working_dir) self._log.debug(f"Cache.del_working_dir(): Deleted working dir: {self.working_dir}") except Exception: self._log.exception(f"Cache.del_working_dir(): Error deleting working dir: {self.working_dir}.") else: self._log.debug("Cache.del_working_dir(): working dir does not exist or use_cache is False")
@property def user_profile(self) -> Path: """Gets user profile path""" try: return self._user_profile except AttributeError: self._user_profile = Path(self.working_dir, self._profile_dir_name) return self._user_profile @property def no_share_path(self) -> Path | None: """Gets user No shared extension path""" try: return None if self._no_shared_ext is False else self._no_share_path except AttributeError: self._no_share_path = Path(self.working_dir, self._no_share_dir_name) return self._no_share_path @property def profile_path(self) -> Path | None: """ Gets/Sets profile path The when possible default is obtained by searching in know locations, depending on OS. For instance on Linux will search in ``~/.config/libreoffice/4`` """ try: return self._profile_path except AttributeError: self._profile_path = self._get_profile_path() self._log.debug(f"Cache.cache_path: {self._profile_path}") return self._profile_path @profile_path.setter def profile_path(self, value: PathOrStr | None): if not value: self._profile_path = None return self._profile_path = Path(value) # type: ignore @property def working_dir(self) -> Path: """ Gets/Sets working dir This property determines the dir LO uses to obtain its profile data. Default to an auto generated tmp dir. """ try: return self._working_dir except AttributeError: self._working_dir = Path(tempfile.mkdtemp()) self._log.debug(f"Cache.working_dir: {self._working_dir}") return self._working_dir @working_dir.setter def working_dir(self, value: PathOrStr): self._working_dir = Path(value) @property def use_cache(self) -> bool: """Gets/Sets if cache is used. Default is ``True``""" return self._use_cache @use_cache.setter def use_cache(self, value: bool) -> None: self._use_cache = value