From 51ce2d82d6938f73fc660a06fbce57ce71f4b81d Mon Sep 17 00:00:00 2001 From: Twentysix Date: Sun, 30 Apr 2017 05:12:00 +0200 Subject: [PATCH] [Core] Added relative_path parameter to json helpers Since these helpers will mostly be used by packages, it's important to make sure that the data they create stays contained inside them. This also brings the additional benefit of being able to manipulate data inside a package without knowing the name of the package's folder itself --- core/bot.py | 3 +-- core/events.py | 2 +- core/utils/helpers.py | 34 ++++++++++++++++++++++++++++------ 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/core/bot.py b/core/bot.py index 35e34c3ab..6ac80c947 100644 --- a/core/bot.py +++ b/core/bot.py @@ -9,8 +9,7 @@ class Red(commands.Bot): def __init__(self, cli_flags, **kwargs): self._shutdown_mode = ExitCodes.CRITICAL self.db = CoreDB("core/data/settings.json", - autosave=True, - create_dirs=True) + relative_path=False) def prefix_manager(bot, message): global_prefix = self.db.get_global("prefix", []) diff --git a/core/events.py b/core/events.py index ca806791b..0598ec173 100644 --- a/core/events.py +++ b/core/events.py @@ -36,7 +36,7 @@ def init_events(bot, cli_flags): failed.append(package) if failed: - bot.save_packages_status() + await bot.save_packages_status() if packages: print("Loaded packages: " + ", ".join(packages)) diff --git a/core/utils/helpers.py b/core/utils/helpers.py index 9f6187292..21f71cb79 100644 --- a/core/utils/helpers.py +++ b/core/utils/helpers.py @@ -2,6 +2,7 @@ import os import discord import asyncio import functools +import inspect from collections import defaultdict from core.json_io import JsonIO @@ -18,23 +19,34 @@ class JsonDB(JsonIO): file_path: str The path of the json file you want to create / access - create_dirs: bool=False + create_dirs: bool=True If True, it will create any missing directory leading to the file you want to create + relative_path: bool=True + The file_path you specified is relative to the path from which + you're instantiating this object from + i.e. If you're in a package's folder and your file_path is + 'data/settings.json', these files will be created inside + the package's folder and not Red's root folder default_value: Optional=None Same behaviour as a defaultdict """ + _caller = "" def __init__(self, file_path, **kwargs): - create_dirs = kwargs.pop("create_dirs", False) + local = kwargs.pop("relative_path", True) + if local and not self._caller: + self._caller = self._get_caller_path() + + create_dirs = kwargs.pop("create_dirs", True) default_value = kwargs.pop("default_value", SENTINEL) self.autosave = kwargs.pop("autosave", False) - self.path = file_path + self.path = os.path.join(self._caller, file_path) - file_exists = os.path.isfile(file_path) + file_exists = os.path.isfile(self.path) if create_dirs and not file_exists: - path, _ = os.path.split(file_path) + path, _ = os.path.split(self.path) if path: try: os.makedirs(path) @@ -43,7 +55,7 @@ class JsonDB(JsonIO): if file_exists: # Might be worth looking into threadsafe ways for very large files - self._data = self._load_json(file_path) + self._data = self._load_json(self.path) else: self._data = {} self._blocking_save() @@ -93,6 +105,12 @@ class JsonDB(JsonIO): """Threadsafe save to file""" await self._threadsafe_save_json(self.path, self._data) + def _get_caller_path(self): + frame = inspect.stack()[2] + module = inspect.getmodule(frame[0]) + abspath = os.path.abspath(module.__file__) + return os.path.dirname(abspath) + def __contains__(self, key): return key in self._data @@ -116,6 +134,10 @@ class JsonGuildDB(JsonDB): """ def __init__(self, *args, **kwargs): + local = kwargs.get("relative_path", True) + if local and not self._caller: + self._caller = self._get_caller_path() + super().__init__(*args, **kwargs) async def set(self, guild, key, value):