diff --git a/README.md b/README.md index 3f3261c..907a7a0 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ ## Install +Python version: >=3.8 + ```python pip3 install --user fiable_db ``` @@ -201,6 +203,32 @@ fiable_db.find_one(id=1) # Default table # {"id": 1, "rev": 1, "data": {"name": "Miguel", "age": 41, "height": 189}} ``` +### Other help functions + +#### Get all data + +Get all data from the database. + +```python +get_database() +``` + +### Load file + +Load a file into the database. + +```python +load(filename) +``` + +### Save file + +Save the database to a file. + +```python +save(filename, data) +``` + ## Implementations in other languages - [Clojure](https://github.com/Toni-zgz/db_inmutable). diff --git a/fiable_db.py b/fiable_db.py index 028afb0..7bc2508 100644 --- a/fiable_db.py +++ b/fiable_db.py @@ -1,43 +1,93 @@ +from os import path +import json +from typing import Dict, Tuple, Union, Sequence, TypedDict + +# Variables FILE = "fiabledb.json" -data = {} +database = {} + +# Type aliases +class TypeData(TypedDict): + id: int + rev: int + data: dict -def start(filename: str = "") -> str: +Type_Data_List = Tuple[TypeData] +Type_Add_Data = Union[Dict, Sequence[Dict]] +Type_Add_Return = Union[Tuple[int, int, Dict], Tuple[Tuple[int, int, Dict]], None] +Type_Update_Return = Union[Tuple[Tuple[int, int, Dict]]] + +Type_Delete_Return = Union[Tuple[Tuple[int, int, Dict]]] +Type_Find_One_Return = TypeData +Type_Find_All_Return = Tuple[Type_Find_One_Return] + + +def start(file_name: str = "") -> str: """Start the database Args: file (str, optional): The file to use. Defaults to FILE. Returns: str: The file used """ - file_name = filename if filename else FILE - print("Function not implemented yet") - return file_name + global database + my_file_name = file_name if file_name else FILE + if path.exists(my_file_name): + # Load the database + load(my_file_name) + else: + # Create the database + save(my_file_name, database) + return my_file_name -def save(filename: str = "", data: list[str, list[int, int, dict]] = {}) -> bool: +def save(file_name: str = "", data: TypeData = {}) -> bool: """Save the database Args: - filename (str, optional): The file to save to. Defaults to "". + file_name (str, optional): The file to save to. Defaults to "". data (list[str, list[int, int, dict]], optional): The data to save. Defaults to {}. Returns: bool: True if the data was saved, False otherwise """ - print("Function not implemented yet") + global database + my_file_name = file_name if file_name else FILE + with open(my_file_name, "w") as f: + database = json.dump({}, f) + return True -def load(filename: str = "") -> list[str, list[int, int, dict]]: +def load(file_name: Union[str, None] = None) -> bool: """Load the database Args: - filename (str, optional): The file to load from. Defaults to "". + file_name (str, optional): The file to load from. Defaults to "". Returns: - list[str, list[int, int, dict]]: The data loaded + Bool - The data loaded """ - print("Function not implemented yet") + global database + my_file_name = file_name if file_name else FILE + is_exists = path.exists(my_file_name) + if is_exists: + with open(my_file_name, "r") as f: + text = f.read() + if text != "": + database = json.loads(text) + else: + database = [] + else: + raise FileNotFoundError("File not found") + return is_exists -def add( - new_data: dict | list, table: str = "" -) -> dict[int, int, dict] | list[dict[int, int, dict]]: +def get_database() -> Type_Data_List: + """Get the data + Returns: + list[dict[int, int, dict]]: The data + """ + global database + return database + + +def add(new_data: Type_Add_Data, table: str = "") -> Type_Add_Return: """Add data to the database Args: new_data (dict|list): The data to add @@ -55,9 +105,8 @@ def add( def update( - id: int, - new_data: dict, table: str = "", force: bool = False -) -> dict[int, int, dict]: + id: int, new_data: dict, table: str = "", force: bool = False +) -> Type_Update_Return: """Update data in the database Args: id (int): The id of the data to update. @@ -70,7 +119,7 @@ def update( print("Function not implemented yet") -def delete(id: int, data: dict, table: str = "") -> dict[int, int, dict]: +def delete(id: int, data: dict, table: str = "") -> Type_Delete_Return: """Delete data from the database Args: id (int): The id of the data to delete @@ -84,7 +133,7 @@ def delete(id: int, data: dict, table: str = "") -> dict[int, int, dict]: def find_one( id: int = 0, data: dict = {}, table: str = "", rev: int = 0 -) -> dict[int, int, dict]: +) -> Type_Find_One_Return: """Find one data in the database Args: id (int, optional): The id of the data to find. Defaults to 0. @@ -97,7 +146,7 @@ def find_one( print("Function not implemented yet") -def find_all(data: dict = {}, table: str = "") -> list[dict[int, int, dict]]: +def find_all(data: dict = {}, table: str = "") -> Type_Find_All_Return: """Find all data in the database Args: data (dict, optional): Filter the data to find. Defaults to {}. diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/example.json b/test/example.json index b2eaaf8..a060d05 100644 --- a/test/example.json +++ b/test/example.json @@ -1,5 +1,29 @@ [ - {"id": 2, "rev": 1, "data": {"name": "Noelia", "age": 34, "height": 165}}, - {"id": 3, "rev": 1, "data": {"name": "Juan", "age": 41, "height": 187}}, - {"id": 4, "rev": 1, "data": {"name": "Valentina", "age": 12, "height": 142}} + { + "id": 2, + "rev": 1, + "data": { + "name": "Noelia", + "age": 34, + "height": 165 + } + }, + { + "id": 3, + "rev": 1, + "data": { + "name": "Juan", + "age": 41, + "height": 187 + } + }, + { + "id": 4, + "rev": 1, + "data": { + "name": "Valentina", + "age": 12, + "height": 142 + } + } ] diff --git a/test/test_save.py b/test/test_save.py deleted file mode 100644 index 2cdc05d..0000000 --- a/test/test_save.py +++ /dev/null @@ -1,7 +0,0 @@ -# content of test_sample.py -def inc(x): - return x + 1 - - -def test_answer(): - assert inc(3) == 5 diff --git a/test/test_start.py b/test/test_start.py index 2438761..0762031 100644 --- a/test/test_start.py +++ b/test/test_start.py @@ -1,40 +1,48 @@ -from fiable_db import start, data +import os +import shutil +from fiable_db import start, get_database + def test_create_new_file(): """Create a new file with a different name""" - filename = 'test.json' + filename = "test.json" start(filename) - assert os.path.isfile(filename) + assert os.path.isfile(filename), "The file does not exist" # Remove the file os.remove(filename) - + def test_create_default_file(): """Create a new file with the default name""" - filename = 'fiabledb.json' + filename = "fiabledb.json" start() - assert os.path.isfile(filename) + assert os.path.isfile(filename), "The file does not exist" # Remove the file os.remove(filename) + def test_read_file_default(): """Read the default file""" - os.copyfile('test/example.json', 'test/fiabledb.json') + input_file = "test/example.json" + output_file = "fiabledb.json" + shutil.copy(input_file, output_file) start() + data = get_database() assert data == [ {"id": 2, "rev": 1, "data": {"name": "Noelia", "age": 34, "height": 165}}, {"id": 3, "rev": 1, "data": {"name": "Juan", "age": 41, "height": 187}}, {"id": 4, "rev": 1, "data": {"name": "Valentina", "age": 12, "height": 142}}, - ] - os.remove('test/fiabledb.json') + ], "The data is not the same: " + str(data) + os.remove(output_file) + - def test_read_file_custom_name(): """Read a file with a custom name""" - filename = 'example.json' + filename = "test/example.json" start(filename) + data = get_database() assert data == [ {"id": 2, "rev": 1, "data": {"name": "Noelia", "age": 34, "height": 165}}, {"id": 3, "rev": 1, "data": {"name": "Juan", "age": 41, "height": 187}}, {"id": 4, "rev": 1, "data": {"name": "Valentina", "age": 12, "height": 142}}, - ] + ], "The data is not the same: " + str(data)