From 0b212966f27bf44bb221f8d42e2d9e9b34309a7b Mon Sep 17 00:00:00 2001
From: Inso <insomniak.fr@gmail.com>
Date: Sun, 8 Mar 2015 18:26:00 +0100
Subject: [PATCH] Persons caching

---
 src/cutecoin/core/app.py         | 25 +++++++++++++++++--
 src/cutecoin/core/person.py      | 42 +++++++++++++++-----------------
 src/cutecoin/gui/currency_tab.py |  2 +-
 src/cutecoin/gui/mainwindow.py   |  1 +
 src/cutecoin/gui/wallets_tab.py  |  2 +-
 src/cutecoin/models/members.py   |  2 +-
 6 files changed, 46 insertions(+), 28 deletions(-)

diff --git a/src/cutecoin/core/app.py b/src/cutecoin/core/app.py
index 87e57836..7ef3a31d 100644
--- a/src/cutecoin/core/app.py
+++ b/src/cutecoin/core/app.py
@@ -15,6 +15,7 @@ from PyQt5.QtCore import QObject, pyqtSignal
 from . import config
 from ..tools.exceptions import NameAlreadyExists, BadAccountFile
 from .account import Account
+from . import person
 from .. import __version__
 
 
@@ -76,8 +77,8 @@ class Application(QObject):
         self.current_account = account
 
     def load(self):
-        if (os.path.exists(config.parameters['data'])
-                and os.path.isfile(config.parameters['data'])):
+        self.load_persons()
+        try:
             logging.debug("Loading data...")
             with open(config.parameters['data'], 'r') as json_data:
                 data = json.load(json_data)
@@ -85,6 +86,18 @@ class Application(QObject):
                     self.default_account = data['default_account']
                 for account_name in data['local_accounts']:
                     self.accounts[account_name] = None
+        except FileNotFoundError:
+            pass
+
+    def load_persons(self):
+        try:
+            persons_path = os.path.join(config.parameters['home'],
+                                        '__persons__')
+            with open(persons_path, 'r') as persons_path:
+                data = json.load(persons_path)
+                person.load_cache(data)
+        except FileNotFoundError:
+            pass
 
     def load_account(self, account_name):
         account_path = os.path.join(config.parameters['home'],
@@ -148,6 +161,14 @@ class Application(QObject):
             account_path = os.path.join(config.parameters['home'], account.name)
             shutil.rmtree(account_path)
 
+    def save_persons(self):
+        persons_path = os.path.join(config.parameters['home'],
+                                    '__persons__')
+        with open(persons_path, 'w')as outfile:
+            data = person.jsonify_cache()
+            data['version'] = __version__
+            json.dump(data, outfile, indent=4, sort_keys=True)
+
     def save_cache(self, account):
         if not os.path.exists(os.path.join(config.parameters['home'],
                                         account.name, '__cache__')):
diff --git a/src/cutecoin/core/person.py b/src/cutecoin/core/person.py
index 11d521cd..2885a2f1 100644
--- a/src/cutecoin/core/person.py
+++ b/src/cutecoin/core/person.py
@@ -16,11 +16,18 @@ from cutecoin.tools.exceptions import PersonNotFoundError,\
 
 
 def load_cache(json_data):
-    for person_data in json_data:
+    for person_data in json_data['persons']:
         person = Person.from_json(person_data)
         Person._instances[person.pubkey] = person
 
 
+def jsonify_cache():
+    data = []
+    for person in Person._instances.values():
+        data.append(person.jsonify())
+    return {'persons': data}
+
+
 class cached(object):
     '''
     Decorator. Caches a function's return value each time it is called.
@@ -30,22 +37,17 @@ class cached(object):
     '''
     def __init__(self, func):
         self.func = func
-        self.cache = {}
 
     def __call__(self, inst, community):
-        try:
-            inst.__cache
-        except AttributeError:
-            inst.__cache = {}
-
-        if community.currency in inst.__cache:
-            if self.func.__name__ in inst.__cache[community.currency]:
-                return inst.__cache[community.currency][self.func.__name__]
+        if community.currency in inst._cache:
+            if self.func.__name__ in inst._cache[community.currency]:
+                return inst._cache[community.currency][self.func.__name__]
         else:
-            inst.__cache[community.currency] = {}
+            inst._cache[community.currency] = {}
 
         value = self.func(inst, community)
-        inst.__cache[community.currency][self.func.__name__] = value
+        inst._cache[community.currency][self.func.__name__] = value
+
         return value
 
     def __repr__(self):
@@ -59,7 +61,7 @@ class cached(object):
 
     def reload(self, inst, community):
         try:
-            del inst.__cache[community.currency][self.func.__name__]
+            del inst._cache[community.currency][self.func.__name__]
             self.__call__(inst, community)
         except KeyError:
             pass
@@ -80,7 +82,7 @@ class Person(object):
         '''
         self.name = name
         self.pubkey = pubkey
-        self.__cache = cache
+        self._cache = cache
 
     @classmethod
     def lookup(cls, pubkey, community, cached=True):
@@ -90,9 +92,6 @@ class Person(object):
         if pubkey in Person._instances:
             return Person._instances[pubkey]
         else:
-            logging.debug("{0} : {1} in ? {2}".format(len(Person._instances),
-                                                      pubkey, pubkey in Person._instances))
-            logging.debug("{0}".format(Person._instances.keys()))
             data = community.request(bma.wot.Lookup, req_args={'search': pubkey},
                                      cached=cached)
             timestamp = 0
@@ -135,6 +134,7 @@ class Person(object):
                 cache = json_person['cache']
             else:
                 cache = {}
+
             person = cls(name, pubkey, cache)
             Person._instances[pubkey] = person
             return person
@@ -181,11 +181,7 @@ class Person(object):
             if '400' in str(e):
                 raise MembershipNotFoundError(self.pubkey, community.name())
 
-        membership = Membership(PROTOCOL_VERSION, community.currency, self.pubkey,
-                                membership_data['blockNumber'],
-                                membership_data['blockHash'], 'IN', search['uid'],
-                                search['sigDate'], None)
-        return membership
+        return membership_data
 
     @cached
     def is_member(self, community):
@@ -256,5 +252,5 @@ class Person(object):
     def jsonify(self):
         data = {'name': self.name,
                 'pubkey': self.pubkey,
-                'cache': self.__cache}
+                'cache': self._cache}
         return data
diff --git a/src/cutecoin/gui/currency_tab.py b/src/cutecoin/gui/currency_tab.py
index fc0da0cd..2c7dfe57 100644
--- a/src/cutecoin/gui/currency_tab.py
+++ b/src/cutecoin/gui/currency_tab.py
@@ -62,7 +62,7 @@ class CurrencyTabWidget(QWidget, Ui_CurrencyTabWidget):
 
         person = Person.lookup(self.app.current_account.pubkey, self.community)
         try:
-            join_block = person.membership(self.community).block_number
+            join_block = person.membership(self.community)['blockNumber']
             join_date = self.community.get_block(join_block).mediantime
             parameters = self.community.get_parameters()
             expiration_date = join_date + parameters['sigValidity']
diff --git a/src/cutecoin/gui/mainwindow.py b/src/cutecoin/gui/mainwindow.py
index 0f49b9f9..4e0d9823 100644
--- a/src/cutecoin/gui/mainwindow.py
+++ b/src/cutecoin/gui/mainwindow.py
@@ -322,6 +322,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
     def closeEvent(self, event):
         if self.app.current_account:
             self.app.save_cache(self.app.current_account)
+        self.app.save_persons()
         self.loader.deleteLater()
         self.loader_thread.deleteLater()
         super().closeEvent(event)
diff --git a/src/cutecoin/gui/wallets_tab.py b/src/cutecoin/gui/wallets_tab.py
index 3af3eb0c..a688f162 100644
--- a/src/cutecoin/gui/wallets_tab.py
+++ b/src/cutecoin/gui/wallets_tab.py
@@ -45,7 +45,7 @@ class WalletsTabWidget(QWidget, Ui_WalletsTab):
             certified = person.certified_by(self.community)
             certifiers = person.certifiers_of(self.community)
 
-            renew_block = membership.block_number
+            renew_block = membership['blockNumber']
             last_renewal = self.community.get_block(renew_block).mediantime
             expiration = last_renewal + parameters['sigValidity']
         except MembershipNotFoundError:
diff --git a/src/cutecoin/models/members.py b/src/cutecoin/models/members.py
index f2f22065..38616205 100644
--- a/src/cutecoin/models/members.py
+++ b/src/cutecoin/models/members.py
@@ -92,7 +92,7 @@ class MembersTableModel(QAbstractTableModel):
 
     def member_data(self, pubkey):
         person = Person.lookup(pubkey, self.community)
-        join_block = person.membership(self.community).block_number
+        join_block = person.membership(self.community)['blockNumber']
         join_date = self.community.get_block(join_block).mediantime
         parameters = self.community.get_parameters()
         expiration_date = join_date + parameters['sigValidity']
-- 
GitLab