1
Fork 0
mirror of https://github.com/RGBCube/JsonWrapper synced 2025-07-27 11:47:45 +00:00

Lots of changes!

(check releases)
This commit is contained in:
RGBCube 2022-03-02 21:08:48 +03:00
parent 5d112701f5
commit 4040aaa9a9
5 changed files with 154 additions and 311 deletions

View file

@ -1,11 +1,14 @@
# 🈷️ JsonWrapper # 🈷️ JsonWrapper
Easy to use JSON wrapper packed with features. Easy to use JSON wrapper packed with features.
# 📥 Usage # 📥 Usage
Execute `pip install json-wrapper`. Execute `pip install json-wrapper`.
Add `from json_wrapper import JsonWrapper` to the top of your project. Add `from json_wrapper import JsonWrapper` to the top of your project.
# 🔗 Important Links # 🔗 Important Links
[Documentation](https://github.com/RGBCube/json-wrapper/blob/main/docs/README.md)
[PyPI: json-wrapper](https://pypi.org/project/json-wrapper/) [PyPI: json-wrapper](https://pypi.org/project/json-wrapper/)

View file

@ -1,66 +0,0 @@
### Table of Contents
* [*class* `json_wrapper.JsonWrapper(json_path: str)`](#class-json_wrapperjsonwrapperjson_path-str)
# *class* `json_wrapper.JsonWrapper(json_path: str)`
### Methods
* [*def* `set(key: str, value, *, pathmagic: Union[str, List[str] = "")`](#def-setkey-str-value--pathmagic-unionstr-liststr--)
* [*def* `get(key: str, *, default=None, pathmagic: Union[str, List[str] = "")`](#def-getkey-str--defaultnone-pathmagic-unionstr-liststr--)
* [*def* `all()`](#def-all)
* [*def* `rem(key: str, *, pathmagic: Union[str, List[str] = "")`](#def-remself-key-str--pathmagic-unionstr-liststr--)
* [*def* `nuke(*, pathmagic: Union[str, List[str] = "")`](#def-nuke-pathmagic-unionstr-liststr--)
## *def* `set(key: str, value, *, pathmagic: Union[str, List[str] = "")`
Sets the key value pair in the json.
If the pathmagic kwarg is given, (if str)it will split it by the +'s and make dicts inside dicts(or use existing ones) until the list ends. Then it will set the key value pair in the last dict.
#### Args
* key (`str`): The key for the key value pair.
* value (`Any`): The value for the key value pair.
* pathmagic (`Union[str, List[str]]`, optional): The path to follow. Defaults to `""`.
#### [Example Usage](https://github.com/RGBCube/json-wrapper/blob/main/examples/set.py)
## *def* `get(key: str, *, default=None, pathmagic: Union[str, List[str] = "")`
Returns the key's value in the json. Will return the default kwarg if not found.
If the pathmagic kwarg is given, (if str)it will split it by the +'s and follow the dicts inside the dicts until the list ends. Then it will return the value of the key in the last dict. The default kwarg applies.
#### Args
* key (`str`): The key to get the value of.
* default (`Any`, optional): The value to return if the key is not found. Defaults to `None`.
* pathmagic (`Union[str, List[str]]`, optional): The path to follow. Defaults to `""`.
#### Returns
* `Any`: The value of the key. Will return the default kwarg if the key is not found.
#### [Example Usage]() TODO
## *def* `all()`
Returns all the json data.
#### Returns
* `dict`: All the json data.
#### [Example Usage]() TODO
## *def* `rem(self, key: str, *, pathmagic: Union[str, List[str]] = "")`
Removes the key value pair in the json.
If the pathmagic kwarg is given, (if str)it will split it by the +'s and follow the dicts inside the dicts until the list ends. Then it will remove the key value pair in the last dict. Does nothing if the key value pair doesn't exist.
#### Args
* key (`str`): The key to remove.
* pathmagic (`Union[str, List[str]]`, optional): The path to follow. Defaults to `""`.
#### [Example Usage]() TODO
## *def* `nuke(*, pathmagic: Union[str, List[str]] = "")`
Nukes the entire database.
If the pathmagic kwarg is given, (if str)it will split it by the +'s and follow the dicts inside the dicts until the list ends. Then it will nuke the last dict.
#### Args
* pathmagic (`Union[str, List[str]]`, optional): The path to follow. Defaults to `""`.
#### [Example Usage]() TODO

View file

@ -1,23 +0,0 @@
from json_wrapper import JsonWrapper # Initialization
db = JsonWrapper("example.json") # Initialization
# set normal
db.set("a", 123)
data = db.all()
print(data) # {'a': 123}
db.nuke()
# set pathmagic
db.set("a", 123, pathmagic="example+path")
data = db.all()
print(data) # {'example': {'path': {'a': 123}}}
db.nuke()

View file

@ -1,266 +1,194 @@
import json import json
import os from typing import Any, Union
from typing import Any, Union, List
class _JsonUtils: class JsonBase:
def __init__(self, json_path: str) -> None: def __init__(self, *, fp: str, indent: int) -> None:
self.json_path = json_path self._fp = fp
self._indent_size = indent
@property
def data(self) -> dict: def data(self) -> dict:
"""Returns all the json data. """Returns the all data of the json file."""
with open(self._fp) as f:
Returns: return json.load(f)
dict: All the json data.
"""
with open(self.json_path, mode="r") as json_file:
return json.load(json_file)
def dump(self, data: dict) -> None: def dump(self, data: dict) -> None:
"""Dumps the dict into the json. """Dumps the data to the json file."""
with open(self._fp, mode="w") as f:
Args: json.dump(data, f, indent=self._indent_size)
data (dict): The data to dump.
"""
with open(self.json_path, mode="w") as json_file:
json.dump(data, json_file, indent=4)
def validate(self) -> None: def validate(self) -> None:
"""Validates the json if the json is not a valid dict. """Validates the json file."""
"""
try: try:
with open(self.json_path, mode="r") as json_file: with open(self._fp, mode="r") as f:
data = json.load(json_file) data = json.load(f)
except (FileNotFoundError, json.JSONDecodeError): except (FileNotFoundError, json.JSONDecodeError):
with open(self.json_path, mode="w") as json_file: with open(self._fp, mode="w") as f:
json.dump({}, json_file) json.dump({}, f)
return return
if not isinstance(data, dict): if not isinstance(data, dict):
with open(self.json_path, mode="w") as json_file: with open(self._fp, mode="w") as f:
json.dump({}, json_file) json.dump({}, f)
class _PathMagic: class JsonWrapper(JsonBase):
@staticmethod def __init__(self, fp: str, *, indent: int = 4) -> None:
def set(main_dict: dict, path: Union[str, List[str]], *, dump: dict) -> dict: super().__init__(fp=fp, indent=indent)
"""Sets the key value pair in the path given. Will override. self.validate()
def get(self, path: str = "", default: Any = None) -> Union[str, int, bool, dict, list, None]:
"""Returns the value of the key in given path. If the key is not found in the path, returns the default value.
Args: Args:
main_dict (dict): The dict to modify. path (str): The path to the key. If the path is not given, returns the whole json as a dict.
path (Union[str, List[str]]): The path to follow. default (Any): The default value.
dump (dict): The key value pairs to set in the last scope.
Returns: Returns:
dict: The modified dict. Union[str, int, bool, dict, list, None]: The value of the key in given path.
""" """
def magic(alt_dict: dict, key: str) -> dict: self.validate()
"""Validates the key(dict) in the alt_dict. path, data = [p for p in path.split(".") if p != ""], self.data
for p in path:
Args: if p not in data:
alt_dict (dict): The dict to modify.
key (str): The key to validate(dict).
Returns:
dict: The modified dict.
"""
if key in alt_dict and isinstance(alt_dict[key], dict):
return alt_dict
alt_dict[key] = {}
return alt_dict
main_dict_ref, i = main_dict, 0
if isinstance(path, str):
path = path.split("+")
for dict_name in path:
i += 1
main_dict = magic(main_dict, dict_name)[dict_name]
if i == len(path):
main_dict.update(dump)
return main_dict_ref
@staticmethod
def get(main_dict: dict, path: Union[str, List[str]], *, key: str, default=None) -> Any:
"""Gets the value for the key in the path given. Will return the default kwarg if the key can't be found.
Args:
main_dict (dict): The dict to get the value of the key in.
path (Union[str, List[str]]): The path to follow.
key (str): The key to get the value of.
default (Any, optional): The value to return if the key is not found. Defaults to None.
Returns:
Any: The value of the key. Will return the default kwarg if the key is not found.
"""
if isinstance(path, str):
path = path.split("+")
for dict_name in path:
try:
main_dict = main_dict[dict_name]
except (KeyError, TypeError, AttributeError):
return default return default
data = data[p]
return data
return main_dict.get(key, default) def set(self, path: str, value: Union[str, int, bool, dict, list, None], *, force: bool = False) -> None:
"""Sets the path to the value. If the path is not found, creates the path.
@staticmethod If the path is blocked by a non-dictionary value, it will raise TypeError, to override this behavior, set force to True.
def rem(main_dict: dict, path: Union[str, List[str]], *, key: str) -> dict:
"""Removes a key value pair from the path given.
Args: Args:
main_dict (dict): The dict to modify. path (str): The path to set the value in.
path (Union[str, List[str]]):The path to follow. value (Union[str, int, bool, dict, list, None]): The value to set.
key (str): The key for the key value pair to remove. force (bool): If True, it overrides the path if the path is blocked by a non-dictionary value.
Raises:
ValueError: If the path is an empty string.
TypeError: If the path is blocked by a non-dictionary value and force is False.
"""
self.validate()
path, data = [p for p in path.split(".") if p != ""], self.data
reference = data
if not path:
raise ValueError("Path is empty.")
for p in path[:-1]:
if p not in data.keys():
data[p] = {}
elif not isinstance(data[p], dict):
if force:
data[p] = {}
else:
raise TypeError("Path is blocked by a non-dictionary value. Use force=True to override.")
data = data[p]
data[path[-1]] = value
self.dump(reference)
def rem(self, path: str = "") -> bool:
"""Removes the key in given path.
Args:
path (str): The path to the key. If the path is not given, nukes the whole json.
Returns: Returns:
dict: The modified dict. bool: True if the key was removed, False if the key was not found.
""" """
main_dict_ref, i = main_dict, 0 self.validate()
path, data = [p for p in path.split(".") if p != ""], self.data
reference = data
if not path:
if data:
self.dump({})
return True
return False
for p in path[:-1]:
if p not in data.keys():
return False
elif not isinstance(data[p], dict):
return False
data = data[p]
if path[-1] not in data.keys():
return False
del data[path[-1]]
self.dump(reference)
return True
if isinstance(path, str): def __contains__(self, key: str) -> bool:
path = path.split("+") self.validate()
return key in self.data
for dict_name in path: def __delitem__(self, key: str) -> None:
try: self.validate()
i += 1 data = self.data
main_dict = main_dict[dict_name] del data[key]
if i == len(path): self.dump(data)
main_dict.pop(key, None)
except (KeyError, TypeError, AttributeError): def __eq__(self, other: Any) -> bool:
return main_dict_ref return self.data == other
return main_dict_ref def __getitem__(self, key: str) -> Union[str, int, bool, dict, list, None]:
self.validate()
return self.data[key]
@staticmethod def __ge__(self, other: Any) -> bool:
def nuke(main_dict: dict, path: Union[str, List[str]]) -> dict: self.validate()
"""Nukes the given path in the main_dict. return self.data >= other
Args: def __gt__(self, other: Any) -> bool:
main_dict (dict): The dict to modify. self.validate()
path (Union[str, List[str]]): The path to follow. return self.data > other
Returns: def __ior__(self, other) -> None:
dict: The modified dict. self.validate()
""" data = self.data
main_dict_ref, i = main_dict, 0 data.update(other)
self.dump(data)
if isinstance(path, str): def __iter__(self):
path = path.split("+") self.validate()
return iter(self.data)
if len(path) == 1: # lazy but works def __len__(self) -> int:
main_dict[path[-1]] = {} self.validate()
return len(self.data)
else: def __le__(self, other: Any) -> bool:
for dict_name in path: self.validate()
try: return self.data <= other
i += 1
main_dict = main_dict[dict_name]
if i == len(path) - 1:
main_dict[path[-1]] = {}
break
except (KeyError, TypeError, AttributeError): def __lt__(self, other: Any) -> bool:
return main_dict_ref self.validate()
return self.data < other
return main_dict_ref def __ne__(self, other: Any) -> bool:
self.validate()
return self.data != other
def __or__(self, other: Any) -> Any:
self.validate()
return self.data | other
class JsonWrapper: def __repr__(self) -> str:
self.validate()
return repr(self.data)
def __init__(self, json_path: str) -> None: def __reversed__(self):
self.json_path = json_path self.validate()
self.pathmagic = _PathMagic return reversed(self.data)
self.json = _JsonUtils(json_path)
self.json.validate()
def set(self, key: str, value, *, pathmagic: Union[str, List[str]] = "") -> None: def __ror__(self, other: Any) -> bool:
"""Sets the key value pair in the json. If the pathmagic kwarg is given, (if str)it will split it by the +'s and make dicts inside dicts(or use existing ones) until the list ends. Then it will set the key value pair in the last dict. self.validate()
return other | self.data
Args: def __setitem__(self, key: str, value: Union[str, int, bool, dict, list, None]) -> None:
key (str): The key for the key value pair. self.validate()
value (Any): The value for the key value pair. data = self.data
pathmagic (Union[str, List[str]], optional): The path to follow. Defaults to "". data[key] = value
""" self.dump(data)
self.json.validate()
json_data = self.json.data() def __sizeof__(self) -> bytes:
self.validate()
if pathmagic in ["", []]: return bytes(self.data)
json_data[key] = value
self.json.dump(json_data)
else:
self.json.dump(self.pathmagic.set(
json_data, pathmagic, dump={key: value}))
def get(self, key: str, *, default=None, pathmagic: Union[str, List[str]] = "") -> Any:
"""Returns the key's value in the json. Will return the default kwarg if not found. If the pathmagic kwarg is given, (if str)it will split it by the +'s and follow the dicts inside the dicts until the list ends. Then it will return the value of the key in the last dict. The default kwarg applies.
Args:
key (str): The key to get the value of.
default (Any, optional): The value to return if the key is not found. Defaults to None.
pathmagic (Union[str, List[str]], optional): The path to follow. Defaults to "".
Returns:
Any: The value of the key. Will return the default kwarg if the key is not found.
"""
self.json.validate()
json_data = self.json.data()
if pathmagic in ["", []]:
return json_data.get(key, default)
else:
return self.pathmagic.get(json_data, pathmagic, key=key, default=default)
def all(self) -> dict: # The same as _JsonUtils.data()
"""Returns all the json data.
Returns:
dict: All the json data.
"""
self.json.validate()
return self.json.data()
def rem(self, key: str, *, pathmagic: Union[str, List[str]] = "") -> None:
"""Removes the key value pair in the json. If the pathmagic kwarg is given, (if str)it will split it by the +'s and follow the dicts inside the dicts until the list ends. Then it will remove the key value pair in the last dict. Does nothing if the key value pair doesn't exist.
Args:
key (str): The key to remove.
pathmagic (Union[str, List[str]], optional): The path to follow. Defaults to "".
"""
self.json.validate()
json_data = self.json.data()
if pathmagic in ["", []]:
json_data.pop(key, None)
self.json.dump(json_data)
else:
self.json.dump(self.pathmagic.rem(
json_data, pathmagic, key=key))
def nuke(self, *, pathmagic: Union[str, List[str]] = "") -> None:
"""Nukes the entire database. If the pathmagic kwarg is given, (if str)it will split it by the +'s and follow the dicts inside the dicts until the list ends. Then it will nuke the last dict.
Args:
pathmagic (Union[str, List[str]], optional): The path to follow. Defaults to "".
"""
if pathmagic in ["", []]:
self.json.dump({})
else:
self.json.dump(self.pathmagic.nuke(self.json.data(), pathmagic))

View file

@ -1,6 +1,7 @@
from setuptools import setup
from pathlib import Path from pathlib import Path
from setuptools import setup
this_directory = Path(__file__).parent this_directory = Path(__file__).parent
long_description = (this_directory / "README.md").read_text() long_description = (this_directory / "README.md").read_text()
@ -10,7 +11,7 @@ setup(
long_description=long_description, long_description=long_description,
long_description_content_type='text/markdown', long_description_content_type='text/markdown',
url="https://github.com/RGBCube/json_wrapper", url="https://github.com/RGBCube/json_wrapper",
version="1.1.0", version="1.2.0",
author="RGBCube", author="RGBCube",
py_modules=["json_wrapper"], py_modules=["json_wrapper"],
license="CC0 1.0 Universal" license="CC0 1.0 Universal"