feat: cache managenent utility

This commit is contained in:
Swann
2020-09-21 16:47:49 +02:00
parent f992d06b03
commit 6c47e095be
5 changed files with 113 additions and 12 deletions

View File

@ -63,16 +63,10 @@ class BlFile(ReplicatedDatablock):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.instance = kwargs.get('instance', None) self.instance = kwargs.get('instance', None)
# TODO: ensure absolute path
# TODO: ensure file exist
self.preferences = utils.get_preferences() self.preferences = utils.get_preferences()
self.diff_method = DIFF_BINARY self.diff_method = DIFF_BINARY
def resolve(self): def resolve(self):
# TODO: generic check
os.makedirs(self.preferences.cache_directory, exist_ok=True)
if self.data: if self.data:
self.instance = Path(get_filepath(self.data['name'])) self.instance = Path(get_filepath(self.data['name']))

View File

@ -27,6 +27,8 @@ from operator import itemgetter
from pathlib import Path from pathlib import Path
from subprocess import PIPE, Popen, TimeoutExpired from subprocess import PIPE, Popen, TimeoutExpired
import zmq import zmq
import shutil
from pathlib import Path
import bpy import bpy
import mathutils import mathutils
@ -608,6 +610,34 @@ class ApplyArmatureOperator(bpy.types.Operator):
stop_modal_executor = False stop_modal_executor = False
class ClearCache(bpy.types.Operator):
"Clear local session cache"
bl_idname = "session.clear_cache"
bl_label = "Modal Executor Operator"
@classmethod
def poll(cls, context):
return True
def execute(self, context):
cache_dir = utils.get_preferences().cache_directory
try:
for root, dirs, files in os.walk(cache_dir):
for name in files:
Path(root, name).unlink()
except Exception as e:
self.report({'ERROR'}, repr(e))
return {"FINISHED"}
def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
row = self.layout
row.label(text=f" Do you really want to remove local cache ? ")
classes = ( classes = (
SessionStartOperator, SessionStartOperator,
SessionStopOperator, SessionStopOperator,
@ -620,7 +650,7 @@ classes = (
ApplyArmatureOperator, ApplyArmatureOperator,
SessionKickOperator, SessionKickOperator,
SessionInitOperator, SessionInitOperator,
ClearCache,
) )

View File

@ -20,6 +20,9 @@ import logging
import bpy import bpy
import string import string
import re import re
import os
from pathlib import Path
from . import bl_types, environment, addon_updater_ops, presence, ui from . import bl_types, environment, addon_updater_ops, presence, ui
from .utils import get_preferences, get_expanded_icon from .utils import get_preferences, get_expanded_icon
@ -68,6 +71,16 @@ def update_port(self, context):
self['ipc_port'] = random.randrange(self.port+4, 10000) self['ipc_port'] = random.randrange(self.port+4, 10000)
def update_directory(self, context):
new_dir = Path(self.cache_directory)
if new_dir.exists() and any(Path(self.cache_directory).iterdir()):
logging.error("The folder is not empty, choose another one.")
self['cache_directory'] = environment.DEFAULT_CACHE_DIR
elif not new_dir.exists():
logging.info("Target cache folder doesn't exist, creating it.")
os.makedirs(self.cache_directory, exist_ok=True)
def set_log_level(self, value): def set_log_level(self, value):
logging.getLogger().setLevel(value) logging.getLogger().setLevel(value)
@ -136,7 +149,8 @@ class SessionPrefs(bpy.types.AddonPreferences):
cache_directory: bpy.props.StringProperty( cache_directory: bpy.props.StringProperty(
name="cache directory", name="cache directory",
subtype="DIR_PATH", subtype="DIR_PATH",
default=environment.DEFAULT_CACHE_DIR) default=environment.DEFAULT_CACHE_DIR,
update=update_directory)
connection_timeout: bpy.props.IntProperty( connection_timeout: bpy.props.IntProperty(
name='connection timeout', name='connection timeout',
description='connection timeout before disconnection', description='connection timeout before disconnection',

View File

@ -19,7 +19,7 @@
import bpy import bpy
from . import operators from . import operators
from .utils import get_preferences, get_expanded_icon from .utils import get_preferences, get_expanded_icon, get_folder_size
from replication.constants import (ADDED, ERROR, FETCHED, from replication.constants import (ADDED, ERROR, FETCHED,
MODIFIED, RP_COMMON, UP, MODIFIED, RP_COMMON, UP,
STATE_ACTIVE, STATE_AUTH, STATE_ACTIVE, STATE_AUTH,
@ -371,7 +371,8 @@ class SESSION_PT_advanced_settings(bpy.types.Panel):
cache_section_row = cache_section.row() cache_section_row = cache_section.row()
cache_section_row.label(text="Clear memory filecache:") cache_section_row.label(text="Clear memory filecache:")
cache_section_row.prop(settings, "clear_memory_filecache", text="") cache_section_row.prop(settings, "clear_memory_filecache", text="")
cache_section_row = cache_section.row()
cache_section_row.operator('session.clear_cache', text=f"Clear cache ({get_folder_size(settings.cache_directory)})")
log_section = layout.row().box() log_section = layout.row().box()
log_section.prop( log_section.prop(
settings, settings,

View File

@ -21,8 +21,10 @@ import logging
import os import os
import sys import sys
import time import time
from uuid import uuid4
from collections.abc import Iterable from collections.abc import Iterable
from pathlib import Path
from uuid import uuid4
import math
import bpy import bpy
import mathutils import mathutils
@ -78,6 +80,7 @@ def resolve_from_id(id, optionnal_type=None):
return root[id] return root[id]
return None return None
def get_datablock_from_uuid(uuid, default, ignore=[]): def get_datablock_from_uuid(uuid, default, ignore=[]):
if not uuid: if not uuid:
return default return default
@ -90,6 +93,7 @@ def get_datablock_from_uuid(uuid, default, ignore=[]):
return item return item
return default return default
def get_preferences(): def get_preferences():
return bpy.context.preferences.addons[__package__].preferences return bpy.context.preferences.addons[__package__].preferences
@ -103,3 +107,61 @@ def get_expanded_icon(prop: bpy.types.BoolProperty) -> str:
return 'DISCLOSURE_TRI_DOWN' return 'DISCLOSURE_TRI_DOWN'
else: else:
return 'DISCLOSURE_TRI_RIGHT' return 'DISCLOSURE_TRI_RIGHT'
# Taken from here: https://stackoverflow.com/a/55659577
def get_folder_size(folder):
return ByteSize(sum(file.stat().st_size for file in Path(folder).rglob('*')))
class ByteSize(int):
_kB = 1024
_suffixes = 'B', 'kB', 'MB', 'GB', 'PB'
def __new__(cls, *args, **kwargs):
return super().__new__(cls, *args, **kwargs)
def __init__(self, *args, **kwargs):
self.bytes = self.B = int(self)
self.kilobytes = self.kB = self / self._kB**1
self.megabytes = self.MB = self / self._kB**2
self.gigabytes = self.GB = self / self._kB**3
self.petabytes = self.PB = self / self._kB**4
*suffixes, last = self._suffixes
suffix = next((
suffix
for suffix in suffixes
if 1 < getattr(self, suffix) < self._kB
), last)
self.readable = suffix, getattr(self, suffix)
super().__init__()
def __str__(self):
return self.__format__('.2f')
def __repr__(self):
return '{}({})'.format(self.__class__.__name__, super().__repr__())
def __format__(self, format_spec):
suffix, val = self.readable
return '{val:{fmt}} {suf}'.format(val=math.ceil(val), fmt=format_spec, suf=suffix)
def __sub__(self, other):
return self.__class__(super().__sub__(other))
def __add__(self, other):
return self.__class__(super().__add__(other))
def __mul__(self, other):
return self.__class__(super().__mul__(other))
def __rsub__(self, other):
return self.__class__(super().__sub__(other))
def __radd__(self, other):
return self.__class__(super().__add__(other))
def __rmul__(self, other):
return self.__class__(super().__rmul__(other))