got rid of the rest of CachedProperty. (its too hacky, and confuses pycharm as well, and now we can actually partually invalidate caches. take that past self!)

This commit is contained in:
Your Name 2024-09-24 18:29:45 +02:00
parent 07542365ac
commit b54c10ef9a
4 changed files with 43 additions and 89 deletions

View File

@ -1,39 +0,0 @@
# NOTE: this should inherit from (object) to function correctly with python 2.7
class CachedProperty(object):
""" A property that is only computed once per instance and
then stores the result in _cached_properties of the object.
Source: https://github.com/bottlepy/bottle/commit/fa7733e075da0d790d809aa3d2f53071897e6f76
"""
def __init__(self, func):
self.__doc__ = getattr(func, '__doc__')
self.func = func
def __get__(self, obj, cls):
if obj is None:
return self
propname = self.func.__name__
if not hasattr(obj, '_cached_properties'):
obj._cached_properties = {}
if propname not in obj._cached_properties:
obj._cached_properties[propname] = self.func(obj)
# value = obj.__dict__[propname] = self.func(obj)
return obj._cached_properties[propname]
@staticmethod
def clear(obj):
"""clears cache of obj"""
if hasattr(obj, '_cached_properties'):
obj._cached_properties = {}
@staticmethod
def is_cached(obj, propname):
if hasattr(obj, '_cached_properties') and propname in obj._cached_properties:
return True
else:
return False

View File

@ -41,7 +41,6 @@ class ZfsDataset:
def invalidate_cache(self):
"""clear caches"""
# CachedProperty.clear(self)
self.force_exists = None
self.__snapshots = None
self.__written_since_ours = None
@ -448,19 +447,6 @@ class ZfsDataset:
seconds = time.mktime(dt.timetuple())
return seconds
# def add_virtual_snapshot(self, snapshot):
# """pretend a snapshot exists (usefull in test mode)"""
#
# # NOTE: we could just call self.snapshots.append() but this would trigger a zfs list which is not always needed.
# if CachedProperty.is_cached(self, 'snapshots'):
# # already cached so add it
# print ("ADDED")
# self.snapshots.append(snapshot)
# else:
# # self.snapshots will add it when requested
# print ("ADDED VIRT")
# self._virtual_snapshots.append(snapshot)
@property
def snapshots(self):
"""get all snapshots of this dataset

View File

@ -8,7 +8,6 @@ import time
from .ExecuteNode import ExecuteNode
from .Thinner import Thinner
from .CachedProperty import CachedProperty
from .ZfsPool import ZfsPool
from .ZfsDataset import ZfsDataset
from .ExecuteNode import ExecuteError
@ -18,7 +17,8 @@ from .util import datetime_now
class ZfsNode(ExecuteNode):
"""a node that contains zfs datasets. implements global (systemwide/pool wide) zfs commands"""
def __init__(self, logger, utc=False, snapshot_time_format="", hold_name="", ssh_config=None, ssh_to=None, readonly=False,
def __init__(self, logger, utc=False, snapshot_time_format="", hold_name="", ssh_config=None, ssh_to=None,
readonly=False,
description="",
debug_output=False, thinner=None, exclude_snapshot_patterns=[]):
@ -30,6 +30,9 @@ class ZfsNode(ExecuteNode):
self.logger = logger
self.__supported_send_options = None
self.__supported_recv_options = None
self.exclude_snapshot_patterns = exclude_snapshot_patterns
if ssh_config:
@ -74,27 +77,30 @@ class ZfsNode(ExecuteNode):
else:
return (keep_snapshots, [])
@CachedProperty
@property
def supported_send_options(self):
"""list of supported options, for optimizing sends"""
# not every zfs implementation supports them all
ret = []
for option in ["-L", "-e", "-c"]:
if self.valid_command(["zfs", "send", option, "zfs_autobackup_option_test"]):
ret.append(option)
return ret
if self.__supported_send_options is None:
self.__supported_send_options = []
for option in ["-L", "-e", "-c"]:
if self.valid_command(["zfs", "send", option, "zfs_autobackup_option_test"]):
self.__supported_send_options.append(option)
return self.__supported_send_options
@CachedProperty
@property
def supported_recv_options(self):
"""list of supported options"""
# not every zfs implementation supports them all
ret = []
for option in ["-s"]:
if self.valid_command(["zfs", "recv", option, "zfs_autobackup_option_test"]):
ret.append(option)
return ret
if self.__supported_recv_options is None:
self.__supported_recv_options = []
for option in ["-s"]:
if self.valid_command(["zfs", "recv", option, "zfs_autobackup_option_test"]):
self.__supported_recv_options.append(option)
return self.__supported_recv_options
def valid_command(self, cmd):
"""test if a specified zfs options are valid exit code. use this to determine support options"""
@ -129,13 +135,12 @@ class ZfsNode(ExecuteNode):
"""
ret=[]
ret = []
for name in names:
ret.append(self.get_dataset(name, force_exists))
return ret
# def reset_progress(self):
# """reset progress output counters"""
# self._progress_total_bytes = 0
@ -275,7 +280,6 @@ class ZfsNode(ExecuteNode):
property_name
])
# The returnlist of selected ZfsDataset's:
selected_filesystems = []
excluded_filesystems = []
@ -298,14 +302,14 @@ class ZfsNode(ExecuteNode):
source = raw_source
# determine it
selected=dataset.is_selected(value=value, source=source, inherited=inherited, exclude_received=exclude_received,
exclude_paths=exclude_paths, exclude_unchanged=exclude_unchanged)
selected = dataset.is_selected(value=value, source=source, inherited=inherited,
exclude_received=exclude_received,
exclude_paths=exclude_paths, exclude_unchanged=exclude_unchanged)
if selected==True:
if selected == True:
selected_filesystems.append(dataset)
elif selected==False:
elif selected == False:
excluded_filesystems.append(dataset)
#returns None when no property is set.
# returns None when no property is set.
return ( selected_filesystems, excluded_filesystems)
return (selected_filesystems, excluded_filesystems)

View File

@ -1,6 +1,3 @@
from .CachedProperty import CachedProperty
class ZfsPool():
"""a zfs pool"""
@ -10,6 +7,10 @@ class ZfsPool():
self.zfs_node = zfs_node
self.name = name
self.__properties = None
def invalidate_cache(self):
self.__properties = None
def __repr__(self):
return "{}: {}".format(self.zfs_node, self.name)
@ -32,22 +33,24 @@ class ZfsPool():
def debug(self, txt):
self.zfs_node.debug("zpool {}: {}".format(self.name, txt))
@CachedProperty
@property
def properties(self):
"""all zpool properties"""
self.debug("Getting zpool properties")
if self.__properties is None:
cmd = [
"zpool", "get", "-H", "-p", "all", self.name
]
self.debug("Getting zpool properties")
ret = {}
cmd = [
"zpool", "get", "-H", "-p", "all", self.name
]
for pair in self.zfs_node.run(tab_split=True, cmd=cmd, readonly=True, valid_exitcodes=[0]):
ret[pair[1]] = pair[2]
self.__properties = {}
return ret
for pair in self.zfs_node.run(tab_split=True, cmd=cmd, readonly=True, valid_exitcodes=[0]):
self.__properties[pair[1]] = pair[2]
return self.__properties
@property
def features(self):