WIP storage
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,3 +2,5 @@
|
|||||||
*.egg*
|
*.egg*
|
||||||
__pycache__
|
__pycache__
|
||||||
/libs/
|
/libs/
|
||||||
|
/backup_box.toml
|
||||||
|
/data/
|
||||||
@@ -2,5 +2,7 @@
|
|||||||
|
|
||||||
|
|
||||||
## Config File
|
## Config File
|
||||||
dir config: ./backup_box.toml
|
|
||||||
user config: C:\Users\<username>\AppData\Local\backup_box\backup_box.toml
|
* additional config: bkb -c (--config) <config_toml_path>
|
||||||
|
* dir config: ./backup_box.toml
|
||||||
|
* user config: C:\Users\<username>\AppData\Local\backup_box\backup_box.toml
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
from . import _env, config
|
from . import _env, config
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from typing import TypedDict
|
from typing import NamedTuple, Literal
|
||||||
|
|
||||||
|
class ArgumentTuple(NamedTuple):
|
||||||
|
config: str
|
||||||
|
action: Literal["gui", "backup", "restore"]
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
p = ArgumentParser()
|
p = ArgumentParser()
|
||||||
@@ -22,16 +25,16 @@ def parse_args():
|
|||||||
p_restore = sps.add_parser("restore")
|
p_restore = sps.add_parser("restore")
|
||||||
p_restore.set_defaults(action="restore")
|
p_restore.set_defaults(action="restore")
|
||||||
# parse args
|
# parse args
|
||||||
args = p.parse_args()
|
args: ArgumentTuple = p.parse_args() # type: ignore # type: ArgumentTuple
|
||||||
# load config file
|
# load config file
|
||||||
config.init_default_config()
|
config.init_default_config()
|
||||||
if args["config"]:
|
if args.config:
|
||||||
config.apply_user_config(args["config"])
|
config.apply_user_config(args.config)
|
||||||
print(args)
|
print("Args:", args)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
config.init_default_config()
|
|
||||||
config.reload_config()
|
|
||||||
print(config.get_config())
|
|
||||||
print("Hello World")
|
|
||||||
parse_args()
|
parse_args()
|
||||||
|
print("Config:", config.get_config())
|
||||||
|
print("Hello World")
|
||||||
|
from .storage import LocalStorage
|
||||||
|
print(LocalStorage.get_storage_type())
|
||||||
|
|||||||
@@ -2,15 +2,30 @@ from . import _env
|
|||||||
from os import path as _pth
|
from os import path as _pth
|
||||||
from tomllib import load as toml_load
|
from tomllib import load as toml_load
|
||||||
from tomli_w import dump as toml_dump
|
from tomli_w import dump as toml_dump
|
||||||
from typing import TypedDict
|
from typing import TypedDict, Literal
|
||||||
|
|
||||||
EntryItem = TypedDict("EntryItem", {
|
EntryItem = TypedDict("EntryItem", {
|
||||||
"source": str,
|
"source": str,
|
||||||
|
"ignored": list[str],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
LocalStorageItem = TypedDict("LocalStorageItem", {
|
||||||
|
"type": Literal["LocalStorageItem"],
|
||||||
|
"path": str,
|
||||||
|
})
|
||||||
|
|
||||||
|
RemoteStorageItem = TypedDict("RemoteStorageItem", {
|
||||||
|
"type": Literal["RemoteStorageItem"],
|
||||||
|
"host": str,
|
||||||
|
"port": str,
|
||||||
|
})
|
||||||
|
|
||||||
|
StorageItem = LocalStorageItem | RemoteStorageItem
|
||||||
|
|
||||||
ConfigDict = TypedDict("ConfigDict", {
|
ConfigDict = TypedDict("ConfigDict", {
|
||||||
"_config": list[str],
|
"_config": list[str],
|
||||||
"entry": dict[str, EntryItem],
|
"entry": dict[str, EntryItem],
|
||||||
|
"storage": dict[str, StorageItem],
|
||||||
})
|
})
|
||||||
|
|
||||||
CONFIG_FILE_NAME = "backup_box.toml"
|
CONFIG_FILE_NAME = "backup_box.toml"
|
||||||
@@ -18,31 +33,51 @@ CONFIG_FILE_NAME = "backup_box.toml"
|
|||||||
def _new_config() -> ConfigDict:
|
def _new_config() -> ConfigDict:
|
||||||
return {
|
return {
|
||||||
"entry": {},
|
"entry": {},
|
||||||
|
"storage": {},
|
||||||
"_config": [],
|
"_config": [],
|
||||||
}
|
}
|
||||||
|
|
||||||
def _override_dict(target: ConfigDict, top_dict: dict):
|
_cfg: ConfigDict = _new_config()
|
||||||
|
|
||||||
|
def _override_dict(target: ConfigDict, top_dict: ConfigDict):
|
||||||
for k, v in top_dict.items():
|
for k, v in top_dict.items():
|
||||||
if isinstance(v, dict) and isinstance(target.get(k, None), dict):
|
if isinstance(v, dict) and isinstance(target.get(k, None), dict):
|
||||||
_override_dict(target[k], v)
|
_override_dict(target[k], v) # type: ignore
|
||||||
else:
|
else:
|
||||||
target[k] = v
|
target[k] = v
|
||||||
|
|
||||||
_cfg: ConfigDict = _new_config()
|
def _path_related_to(base: str, *sub: str):
|
||||||
|
return _pth.abspath(_pth.join(base, *sub))
|
||||||
|
|
||||||
def apply_user_config(dir_or_path: str):
|
def apply_user_config(dir_or_path: str):
|
||||||
if _pth.isdir(dir_or_path):
|
if _pth.isdir(dir_or_path):
|
||||||
dir_or_path = _pth.abspath(_pth.join(dir_or_path, CONFIG_FILE_NAME))
|
dir_or_path = _pth.abspath(_pth.join(dir_or_path, CONFIG_FILE_NAME))
|
||||||
|
cfg_dir = _pth.dirname(dir_or_path)
|
||||||
if dir_or_path in _cfg["_config"]:
|
if dir_or_path in _cfg["_config"]:
|
||||||
return # skip if already added
|
return # skip if already added
|
||||||
try:
|
try:
|
||||||
with open(dir_or_path, "rb") as f:
|
with open(dir_or_path, "rb") as f:
|
||||||
config = toml_load(f)
|
config: ConfigDict = toml_load(f) # type: ignore
|
||||||
except:
|
except:
|
||||||
config = {}
|
config: ConfigDict = {} # type: ignore
|
||||||
# ignore config file list
|
# ignore config file list
|
||||||
if "_config" in config:
|
if "_config" in config:
|
||||||
del config["_config"]
|
del config["_config"] # type: ignore
|
||||||
|
# ensure default value
|
||||||
|
config.setdefault("entry", {})
|
||||||
|
for item in config["entry"].values():
|
||||||
|
item.setdefault("source", "")
|
||||||
|
# path related to the config file.
|
||||||
|
if item["source"]:
|
||||||
|
item["source"] = _path_related_to(cfg_dir, item["source"])
|
||||||
|
item.setdefault("ignored", [])
|
||||||
|
config.setdefault("storage", {})
|
||||||
|
for item in config["storage"].values():
|
||||||
|
if item["type"] == "LocalStorageItem":
|
||||||
|
item.setdefault("path", "")
|
||||||
|
# path related to the config file.
|
||||||
|
if item["path"]:
|
||||||
|
item["path"] = _path_related_to(cfg_dir, item["path"])
|
||||||
# update config
|
# update config
|
||||||
_override_dict(_cfg, config)
|
_override_dict(_cfg, config)
|
||||||
# append config file list
|
# append config file list
|
||||||
|
|||||||
5
backup_box/storage/__init__.py
Normal file
5
backup_box/storage/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
from .local_storage import LocalStorage
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"LocalStorage"
|
||||||
|
]
|
||||||
4
backup_box/storage/local_storage.py
Normal file
4
backup_box/storage/local_storage.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from .storage import Storage
|
||||||
|
|
||||||
|
class LocalStorage(Storage):
|
||||||
|
pass
|
||||||
12
backup_box/storage/storage.py
Normal file
12
backup_box/storage/storage.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from ..config import StorageItem
|
||||||
|
|
||||||
|
class Storage(ABC):
|
||||||
|
@classmethod
|
||||||
|
def get_storage_type(cls) -> str:
|
||||||
|
return cls.__name__ + "Item"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def from_config(cls, cfg: StorageItem) -> 'Storage':
|
||||||
|
...
|
||||||
@@ -1 +1 @@
|
|||||||
# tui
|
# tui
|
||||||
|
|||||||
Reference in New Issue
Block a user