Advertisement
Uno-Dan

Updated Again

Sep 12th, 2019
310
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.52 KB | None | 0 0
  1. ########################################################################################################################
  2. #    File: cache.py
  3. #  Author: Dan Huckson, https://github.com/unodan
  4. #    Date: 2019-09-07
  5. ########################################################################################################################
  6.  
  7. from os import path, makedirs
  8. from json import load, dump
  9. from copy import deepcopy
  10. from importlib.util import module_from_spec, spec_from_file_location
  11.  
  12.  
  13. def uri2dict(uri, value):
  14.     node = output = {}
  15.     parts = uri.split('/')
  16.  
  17.     while parts:
  18.         _path = parts.pop(0)
  19.         node[_path] = node = {}
  20.  
  21.     c = Cache(**output)
  22.     c.set(uri, value)
  23.     return c.get()
  24.  
  25.  
  26. class Cache:
  27.     def __init__(self, *args, **kwargs):
  28.         self.nodes = {}
  29.  
  30.         arg = args[0] if args else kwargs
  31.         if arg:
  32.             key = next(iter(arg.keys()))
  33.             value = next(iter(arg.values()))
  34.             if '/' in key:
  35.                 self.set(key, value)
  36.             else:
  37.                 self.nodes = arg
  38.  
  39.         self.indent = '.'
  40.  
  41.     def __eq__(self, other):
  42.         if self.nodes == other.nodes:
  43.             return True
  44.         return False
  45.  
  46.     def __str__(self):
  47.         return str(self.nodes.items())
  48.  
  49.     def __repr__(self):
  50.         data = "**{'key': 'value'}"
  51.         return f"{self.__class__.__name__}({data})"
  52.  
  53.     def get(self, uri=None):
  54.         if not uri:
  55.             return self.nodes
  56.  
  57.         def walk(_uri, nodes):
  58.             parts = _uri.split('/', 1)
  59.             key = parts.pop(0)
  60.  
  61.             if key in nodes:
  62.                 node = nodes[key]
  63.  
  64.                 if not parts:
  65.                     return node
  66.                 else:
  67.                     return walk(parts[0], node)
  68.  
  69.         return walk(uri, self.nodes)
  70.  
  71.     def set(self, uri, *args, **kwargs):
  72.         data = args[0] if args else kwargs
  73.  
  74.         def walk(_uri, nodes):
  75.             parts = _uri.split('/', 1)
  76.             key = parts.pop(0)
  77.  
  78.             if key in nodes and parts:
  79.                 walk(parts[0], nodes[key])
  80.             elif len(_uri.split('/')) == 1:
  81.                 nodes[key] = data
  82.             else:
  83.                 self.nodes.update(**uri2dict(_uri, data))
  84.  
  85.         walk(uri, self.nodes)
  86.  
  87.     def dump(self, indent=None):
  88.         """ Dumps the contents of the cache to the screen.
  89.        The output from dump goes stdout and is used to view the cache contents.
  90.        Default indentation is a dot for each level.
  91.        :param indent:
  92.            indent (str): String to be use for indenting levels.
  93.        :return:
  94.            Nothing.
  95.        """
  96.         indent = indent if indent else '.'
  97.  
  98.         print('-------------------------------------------------------------------------------------------------------')
  99.         print('id =', id(self), '\nnodes =', self)
  100.         if self.nodes:
  101.             def walk(_cfg, count):
  102.                 count += 1
  103.                 for key, value in _cfg.items():
  104.                     if isinstance(value, dict):
  105.                         print(indent * count, key)
  106.                         walk(value, count)
  107.                     else:
  108.                         if isinstance(value, str):
  109.                             value = f'"{value}"'
  110.                         print(indent * count, key, f'value={value}')
  111.             walk(self.nodes, 0)
  112.         else:
  113.             print(' (No Data)')
  114.  
  115.         print('-------------------------------------------------------------------------------------------------------')
  116.  
  117.     def save(self, file=None):
  118.         if file:
  119.             dirname = path.dirname(file)
  120.  
  121.             if dirname and not path.exists(dirname):
  122.                 makedirs(dirname)
  123.  
  124.             with open(file, 'w') as f:
  125.                 dump(self.nodes, f, indent=3)
  126.  
  127.     def load(self, file=None):
  128.         file_type = path.splitext(file)[1].lstrip('.').lower()
  129.  
  130.         if file_type == 'py' and path.exists(file):
  131.             spec = spec_from_file_location("module.name", file)
  132.             module = module_from_spec(spec)
  133.             spec.loader.exec_module(module)
  134.             self.nodes = module.config
  135.  
  136.         if file_type == 'json' and path.exists(file):
  137.             with open(file) as f:
  138.                 self.nodes = load(f)
  139.  
  140.     def copy(self):
  141.         return Cache(**deepcopy(self.nodes))
  142.  
  143.     def remove(self, uri):
  144.         """ Remove entree from cache.
  145.        Removes an entree from the cache if it exists.
  146.        :param uri:
  147.            uri (str): URI that points to the entree to remove.
  148.        :return:
  149.            Nothing.
  150.        """
  151.  
  152.         uri = uri.lstrip('/')
  153.         if self.exists(uri):
  154.             node = self.get('/'.join(uri.split('/')[:-1]))
  155.             del node[uri.split('/')[-1]]
  156.  
  157.     def exists(self, uri):
  158.         """ Test if URI exists in the cache.
  159.  
  160.        :param uri:
  161.        :return:
  162.        """
  163.         return True if self.get(uri) else False
  164.  
  165.     def destroy(self):
  166.         """ Destroy cache.
  167.        Deletes all entries in the cache.
  168.        :return:
  169.            Nothing.
  170.        """
  171.         del self.nodes
  172.         self.nodes = {}
  173.  
  174.     def has_nodes(self):
  175.         if len(self.nodes):
  176.             return True
  177.         return False
  178. # If uncommented the cache will ba a singleton.
  179. # class Cache:
  180. #     instance = None
  181. #
  182. #     def __new__(cls, **kwargs):
  183. #         if not cls.instance:
  184. #             cls.instance = super(Cache, cls).__new__(cls)
  185. #             cls.instance.cache = _Cache(**kwargs)
  186. #
  187. #         return cls.instance.cache
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement