From 7e5ce5fba6b136a1c7acf11115a0bb1c00efa2be Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Wed, 2 Nov 2022 07:06:08 +0530 Subject: [PATCH 01/16] updating first package --- CODE_OF_CONDUCT.md | 76 ++++++++++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 79 ++++++++++++++++++++++++++++++++++++++++++++++ README.md | 44 ++++++++++++++++++++------ quickdb_/main.py | 17 +++++----- setup.py | 2 +- test.sh | 31 ++++++++++++++++++ 6 files changed, 230 insertions(+), 19 deletions(-) create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 test.sh diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..b7954f8 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at pycontributors@gmail.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ac1a30e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,79 @@ +# Contributing to QuickDB + +We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: + +- Reporting a bug +- Discussing the current state of the code +- Submitting a fix +- Proposing new features +- Becoming a maintainer + +## Steps to contribute + +- Comment on the issue you want to work on. Make sure it's not assigned to someone else. + +### Making a PR + +> - Make sure you have been assigned the issue to which you are making a PR. +> - If you make PR before being assigned, It may be labeled `invalid` and closed without merging. + +- Fork the repo and clone it on your machine. +- Add a upstream link to main branch in your cloned repo + + ```sh + git remote add upstream https://github.com/py-contributors/quickdb.git + ``` + +- Keep your cloned repo upto date by pulling from upstream (this will also avoid any merge conflicts while committing new changes) + + ```sh + git pull upstream master + ``` + +- Create your feature branch + + ```sh + git checkout -b + ``` + +- Commit all the changes + + ```sh + git commit -am "Meaningful commit message" + ``` + +- Push the changes for review + + ```sh + git push origin + ``` + +- Create a PR from our repo on Github. + +### Additional Notes + +- Any changes should be made in the `dev` branch. +- Changes should be logged in the `CHANGELOG.md` file. +- Code should be properly commented to ensure it's readability. +- If you've added code that should be tested, add tests as comments. +- Make sure your code properly formatted. +- Issue that pull request! + +## Issue suggestions/Bug reporting + +When you are creating an issue, make sure it's not already present. Furthermore, provide a proper description of the changes. If you are suggesting any code improvements, provide through details about the improvements. + +**Great Issue suggestions** tend to have: + +- A quick summary of the changes. +- In case of any bug provide steps to reproduce + - Be specific! + - Give sample code if you can. + - What you expected would happen + - What actually happens + - Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) + + +## License + +By contributing, you agree that your contributions will be licensed under its [MIT License](http://choosealicense.com/licenses/mit/). diff --git a/README.md b/README.md index 67c0e49..5f8c00c 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -# python-db +

Quick DB ⚡ 0.0.1

+

Light weight database for python, with a simple API and a simple file format. it is not meant to be a full featured database, but rather a simple way to store data in a file. -it's written in python, and is compatible with python 3.6 and above. - +it's written in python, and is compatible with python 3.6 and above.

## Features @@ -13,19 +13,43 @@ it's written in python, and is compatible with python 3.6 and above. * CLI interface * Open source -## Documentation +## Documentation/Tutorial -The documentation is available at [not yet available]() +The documentation is available at [Quick DB]](https://quickdb.readthedocs.io/en/latest/) ## Installation -You can install python-db using pip: - - pip install python-db +You can install the package using pip: +```bash +pip install quickdatabase +``` ## Usage -To use python-db, you need to import it: +To use QuickDB, you need to import it: + +```bash +from quickdb import QuickDB +``` + +## CONTRIBUTING + +If you want to contribute to this project, you can do so by forking the repository and making a pull request. +Check out the [CONTRIBUTING.md](/CONTRIBUTING.md) file for more information. + +## LICENSE + +This project is licensed under the MIT License - see the [LICENSE](/LICENSE) file for details + +## COntributors + + + + + +## Author - from python_db import Database +- Module : QuickDB +- Author : py-contributors +- Email : pycontributors@gmail.com diff --git a/quickdb_/main.py b/quickdb_/main.py index ed01209..f39ecee 100644 --- a/quickdb_/main.py +++ b/quickdb_/main.py @@ -4,18 +4,19 @@ from colorama import Fore, Style -def print_it(color, text): - if color == "red": - print(Fore.RED + text + Style.RESET_ALL) - elif color == "green": - print(Fore.GREEN + text + Style.RESET_ALL) - elif color == 'blue': - print(Fore.BLUE + text + Style.RESET_ALL) +def print_it(color, text, print_it=True): + if print_it: + if color == "red": + print(Fore.RED + text + Style.RESET_ALL) + elif color == "green": + print(Fore.GREEN + text + Style.RESET_ALL) + elif color == 'blue': + print(Fore.BLUE + text + Style.RESET_ALL) class QuickDB(object): """ python database.py """ - def __init__(self, db_path, overwrite_db=False): + def __init__(self, db_path, overwrite_db=False, print_it=True): self.db_path = db_path self.db = self.__init_db(overwrite_db) diff --git a/setup.py b/setup.py index 2a848a7..399bc2e 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ long_description = fh.read() setuptools.setup( - name="quickDB", + name="quickDatabase", version="0.0.1", author="Deepak Raj", author_email="deepak008@live.com", diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..2fc1136 --- /dev/null +++ b/test.sh @@ -0,0 +1,31 @@ +#!/bin/bash +if ! [ -x "$(command -v flake8)" ]; then + echo 'Error: flake8 is not installed.' >&2 + echo 'Installing flake8...' + pip install flake8 +fi + +if ! [ -x "$(command -v twine)" ]; then + echo 'Error: twine is not installed.' >&2 + echo 'Installing twine...' + pip install twine +fi + +if ! [ -f "setup.py" ]; then + echo 'Error: setup.py is not found.' >&2 + exit 1 +fi + +python3 setup.py bdist sdist bdist_wheel + +if ! [ -d "dist" ]; then + echo 'Error: dist folder is not found.' >&2 + exit 1 +fi + +python3 -m twine upload dist/* + +rm -rf dist +rm -rf build +rm -rf *.egg-info +find . -name "*.pyc" -exec rm -rf {}\; From 7b757d02b4994e4d7e3f862139ba98b4bae6b001 Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Wed, 2 Nov 2022 07:57:40 +0530 Subject: [PATCH 02/16] cli: support added --- README.md | 4 +- docs/conf.py | 2 +- {quickdb_ => quickdb}/__init__.py | 2 +- quickdb/cli.py | 35 +++++++++++++ {quickdb_ => quickdb}/main.py | 60 +++++++++++------------ {quickdb_ => quickdb}/tests/test_cases.py | 16 +++--- quickdb_/cli.py | 3 -- test.py | 10 ---- 8 files changed, 76 insertions(+), 56 deletions(-) rename {quickdb_ => quickdb}/__init__.py (60%) create mode 100644 quickdb/cli.py rename {quickdb_ => quickdb}/main.py (59%) rename {quickdb_ => quickdb}/tests/test_cases.py (92%) delete mode 100644 quickdb_/cli.py delete mode 100644 test.py diff --git a/README.md b/README.md index 5f8c00c..5112e58 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ it's written in python, and is compatible with python 3.6 and above.

## Features * Simple API -* Colorful output -* Easy to use +* CLI support with colorful output +* Easy to use * CLI interface * Open source diff --git a/docs/conf.py b/docs/conf.py index 0d8b198..8e69d8d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -13,4 +13,4 @@ html_theme = 'sphinx_rtd_theme' # 'pydata_sphinx_theme' 'alabaster' html_static_path = ['_static'] exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.venv'] -html_sidebars = { '**': ['globaltoc.html', 'relations.html', 'sourcelink.html', 'searchbox.html'] } \ No newline at end of file +html_sidebars = {'**': ['globaltoc.html', 'relations.html', 'sourcelink.html', 'searchbox.html']} diff --git a/quickdb_/__init__.py b/quickdb/__init__.py similarity index 60% rename from quickdb_/__init__.py rename to quickdb/__init__.py index d90e796..2471f9f 100644 --- a/quickdb_/__init__.py +++ b/quickdb/__init__.py @@ -1,3 +1,3 @@ from quickdb.main import QuickDB -__all__ = ['QuickDB'] \ No newline at end of file +__all__ = ['QuickDB'] diff --git a/quickdb/cli.py b/quickdb/cli.py new file mode 100644 index 0000000..cc68e4c --- /dev/null +++ b/quickdb/cli.py @@ -0,0 +1,35 @@ +from quickdb import QuickDB +import argparse + +argparse = argparse.ArgumentParser(description="QuickDB CLI") +argparse.add_argument("-p", "--db_path", help="Path to the database file", required=True) + +group = argparse.add_mutually_exclusive_group(required=True) +group.add_argument("-s", "--set", help="Set a key-value pair in the database") +group.add_argument("-g", "--get", help="Get a value from the database") +group.add_argument("-d", "--delete", help="Delete a key-value pair from the database") +group.add_argument("-c", "--clear", help="Clear the database", action="store_true") +args = argparse.parse_args() + +db = QuickDB(args.db_path, overwrite_db=False, print_output=True) + + +def main(): + if args.set: + key, value = args.set.split("=") + db.set(key, value) + elif args.get: + key = args.get + print(db.get(key)) + elif args.delete: + key = args.delete + db.delete(key) + elif args.clear: + db.clear() + else: + print("Invalid arguments") + # check if the command is similar to any of the commands + + +if __name__ == "__main__": + main() diff --git a/quickdb_/main.py b/quickdb/main.py similarity index 59% rename from quickdb_/main.py rename to quickdb/main.py index f39ecee..65c58d6 100644 --- a/quickdb_/main.py +++ b/quickdb/main.py @@ -4,38 +4,39 @@ from colorama import Fore, Style -def print_it(color, text, print_it=True): - if print_it: - if color == "red": - print(Fore.RED + text + Style.RESET_ALL) - elif color == "green": - print(Fore.GREEN + text + Style.RESET_ALL) - elif color == 'blue': - print(Fore.BLUE + text + Style.RESET_ALL) - - class QuickDB(object): """ python database.py """ - def __init__(self, db_path, overwrite_db=False, print_it=True): + def __init__(self, db_path, overwrite_db=False, print_output=True): self.db_path = db_path + self.print_output = print_output self.db = self.__init_db(overwrite_db) + def print_it(self, color, text, print_output=True): + if self.print_output: + if color == "red": + print(Fore.RED, text) + elif color == "green": + print(Fore.GREEN, text) + elif color == 'blue': + print(Fore.BLUE, text) + print(Style.RESET_ALL, end='') + def __load_db_from_file(self): with open(self.db_path, 'r') as f: return json.load(f) - + def __init_db(self, overwrite_db): if not overwrite_db and os.path.exists(self.db_path): - print_it("green", "Loading database from file") + self.print_it("green", "Loading database from file") return self.__load_db_from_file() - + elif overwrite_db and os.path.exists(self.db_path): - print_it("blue", "Overwriting database") + self.print_it("blue", "Overwriting database") self.clear() return self.db - + elif not os.path.exists(self.db_path): - print_it("green", "Creating new database") + self.print_it("green", "Creating new database") return {} def __dump_db(self, data): @@ -43,23 +44,23 @@ def __dump_db(self, data): with open(self.db_path, 'w+') as f: json.dump(data, f, indent=4) return True - except Exception as e: + except Exception: return False def set(self, key, value, overwrite=False): if key not in self.db: - print_it("green", "Key is not present in the database, adding in the database") + self.print_it("green", "Key is not present in the database, adding in the database") self.db[key] = value self.__dump_db(self.db) return True - + elif not overwrite and key in self.db: - print_it("red", "Key already exists") + self.print_it("red", "Key already exists") return False - + elif overwrite and key in self.db: - print_it("blue", "Key already exists, overwriting the value") + self.print_it("blue", "Key already exists, overwriting the value") self.db[key] = value self.__dump_db(self.db) return True @@ -68,24 +69,23 @@ def get(self, key): if key in self.db: return self.db[key] else: - print_it("red", "Key not found") + self.print_it("red", "Key not found") return False - + def delete(self, key): if key in self.db: del self.db[key] self.__dump_db(self.db) - print_it("green", "Key deleted") + self.print_it("green", "Key deleted") else: - print_it("red", "Key not found") + self.print_it("red", "Key not found") def get_db(self): print(self.db) return self.db - + def clear(self): self.db = {} self.__dump_db(self.db) - print_it("green", "Database cleared") + self.print_it("green", "Database cleared") return True - diff --git a/quickdb_/tests/test_cases.py b/quickdb/tests/test_cases.py similarity index 92% rename from quickdb_/tests/test_cases.py rename to quickdb/tests/test_cases.py index 36e4f0d..13e79b0 100644 --- a/quickdb_/tests/test_cases.py +++ b/quickdb/tests/test_cases.py @@ -1,13 +1,12 @@ -import sys -sys.path.append('.') import unittest from quickdb.main import QuickDB db = QuickDB("test_db.json", overwrite_db=True) + class DatabaseTest(unittest.TestCase): - + def test_operation_one(self): """ if key does not exist, it should be added """ self.assertTrue(db.set("name", "john")) @@ -15,20 +14,19 @@ def test_operation_one(self): self.assertTrue(db.set("age", 30, overwrite=True)) self.assertEqual(db.get_db(), {'name': 'john', 'age': 30}) self.assertTrue(db.clear(), True) - + def test_operation_two(self): """ if key already exists, it should not be added """ self.assertTrue(db.set("name", "john")) self.assertFalse(db.set("name", "john")) self.assertTrue(db.clear(), True) - + def test_operation_three(self): """ if key already exists, it should be overwritten """ self.assertTrue(db.set("name", "john")) self.assertTrue(db.set("name", "john", overwrite=True)) self.assertTrue(db.clear(), True) - - - + + if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/quickdb_/cli.py b/quickdb_/cli.py deleted file mode 100644 index 4d2e254..0000000 --- a/quickdb_/cli.py +++ /dev/null @@ -1,3 +0,0 @@ -from quickdb.main import QuickDB -import argparse - diff --git a/test.py b/test.py deleted file mode 100644 index e4ac932..0000000 --- a/test.py +++ /dev/null @@ -1,10 +0,0 @@ -from quickdb.main import QuickDB - -db = QuickDB("test_db.json", overwrite_db=True) -db.set("name", "John") -db.set("age", 25) -db.set("age", 30, overwrite=True) -print(db.get("name")) -print(db.get("age")) - -db.get_db() \ No newline at end of file From 596ac6e6692eaf3ff8f68dd211bf2d389a25ab4d Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Wed, 2 Nov 2022 08:03:52 +0530 Subject: [PATCH 03/16] update readme --- README.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5112e58..a8ac4c9 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,21 @@ Light weight database for python, with a simple API and a simple file format. it is not meant to be a full featured database, but rather a simple way to store data in a file. it's written in python, and is compatible with python 3.6 and above.

+

+github stars +github forks +code size +

+

+pypi status +docs +dependices +

+

+discord invite +total contributors +

+ ## Features * Simple API @@ -15,7 +30,7 @@ it's written in python, and is compatible with python 3.6 and above.

## Documentation/Tutorial -The documentation is available at [Quick DB]](https://quickdb.readthedocs.io/en/latest/) +The documentation is available at [Quick DB](https://quickdb.readthedocs.io/en/latest/) ## Installation @@ -42,7 +57,7 @@ Check out the [CONTRIBUTING.md](/CONTRIBUTING.md) file for more information. This project is licensed under the MIT License - see the [LICENSE](/LICENSE) file for details -## COntributors +## Contributors From 6abe37e848e06bfcfd48dbbe6429c5449834de00 Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Sat, 5 Nov 2022 12:42:20 +0530 Subject: [PATCH 04/16] updating cli and docs --- docs/as_command_line.rst | 42 ++++++++++++++++++++++++++++++ docs/as_module.rst | 0 docs/index.rst | 14 +++++++++- docs/installation.rst | 20 +++++++++++++++ quickdb/cli.py | 19 +++++++++++--- quickdb/main.py | 51 ++++++++++++++++++++++--------------- quickdb/tests/test_cases.py | 3 +++ setup.py | 4 +-- test.sh | 31 ---------------------- 9 files changed, 126 insertions(+), 58 deletions(-) create mode 100644 docs/as_command_line.rst create mode 100644 docs/as_module.rst create mode 100644 docs/installation.rst delete mode 100644 test.sh diff --git a/docs/as_command_line.rst b/docs/as_command_line.rst new file mode 100644 index 0000000..1918a06 --- /dev/null +++ b/docs/as_command_line.rst @@ -0,0 +1,42 @@ +Command line Usages +================== + +.. code-block:: bash + + --debug Enable debug mode + -v, --version show program's version number and exit + -p path to the database + + -s SET, --set SET Set a key-value pair in the database + -g GET, --get GET Get a value from the database + -d DELETE, --delete DELETE + Delete a key-value pair from the database + -c, --clear Clear the database + + -o --overwrite to overwrite the value if the key already exists + +Set a key-value pair in the database + +.. code-block:: bash + quickdb -p test.db -s key=value + + # if the key already exists, overwrite the value by adding the -o flag + quickdb -p test.db -s key=value -o + +Get a value from the database + +.. code-block:: bash + quickdb -p test.db -g key + +Delete a key-value pair from the database + +.. code-block:: bash + quickdb -p test.db -d key + + +Clear the database + +.. code-block:: bash + quickdb -p test.db -c + +use --debug to enable debug mode with colored output diff --git a/docs/as_module.rst b/docs/as_module.rst new file mode 100644 index 0000000..e69de29 diff --git a/docs/index.rst b/docs/index.rst index 0d45f4c..3239007 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -4,4 +4,16 @@ Welcome to QuickDB's documentation! ===================================== -![Download badge](http://pepy.tech/badge/pickledb) \ No newline at end of file +Light weight database for python, with a simple API and a simple file format. +it is not meant to be a full featured database, but rather a simple way to store data in a file. +it's written in python, and is compatible with python 3.6 and above. + +Features +-------- + +- Simple API +- CLI support with colorful output +- Easy to use +- CLI interface +- Open source + diff --git a/docs/installation.rst b/docs/installation.rst new file mode 100644 index 0000000..32cce5a --- /dev/null +++ b/docs/installation.rst @@ -0,0 +1,20 @@ +Installation +============ + +Install Via Pip(recommended) +--------------------------- + +.. code-block:: bash + + pip install quickdatabase + +Install Via Source(Unreleased/latest) +----------------- + +.. code-block:: bash + + git clone https://github.com/py-contributors/quickdb + cd quickdb + python setup.py install + + \ No newline at end of file diff --git a/quickdb/cli.py b/quickdb/cli.py index cc68e4c..2c3e1b3 100644 --- a/quickdb/cli.py +++ b/quickdb/cli.py @@ -1,8 +1,16 @@ -from quickdb import QuickDB import argparse +import sys + +sys.path.append(".") +from quickdb import QuickDB + +version = "quickdb 0.0.2" argparse = argparse.ArgumentParser(description="QuickDB CLI") +argparse.add_argument("--debug", action="store_true", help="Enable debug mode") argparse.add_argument("-p", "--db_path", help="Path to the database file", required=True) +argparse.add_argument("-o", "--overwrite", help="Overwrite the database", action="store_true") +argparse.add_argument('-v', '--version', action='version', version=version) group = argparse.add_mutually_exclusive_group(required=True) group.add_argument("-s", "--set", help="Set a key-value pair in the database") @@ -11,13 +19,18 @@ group.add_argument("-c", "--clear", help="Clear the database", action="store_true") args = argparse.parse_args() -db = QuickDB(args.db_path, overwrite_db=False, print_output=True) +debug = True if args.debug else False + +db = QuickDB(args.db_path, overwrite_db=False, debug=debug) def main(): if args.set: key, value = args.set.split("=") - db.set(key, value) + if args.overwrite: + db.set(key, value, overwrite=True) + else: + db.set(key, value) elif args.get: key = args.get print(db.get(key)) diff --git a/quickdb/main.py b/quickdb/main.py index 65c58d6..17dbd8b 100644 --- a/quickdb/main.py +++ b/quickdb/main.py @@ -3,43 +3,52 @@ from colorama import Fore, Style +colors_dict = { + 'red' : Fore.RED, + 'green' : Fore.GREEN, + 'yellow' : Fore.YELLOW, + 'blue' : Fore.BLUE, + 'magenta' : Fore.MAGENTA, + 'cyan' : Fore.CYAN, + 'white' : Fore.WHITE, + 'reset' : Style.RESET_ALL +} + class QuickDB(object): """ python database.py """ - def __init__(self, db_path, overwrite_db=False, print_output=True): + def __init__(self, db_path, overwrite_db=False, debug=True): self.db_path = db_path - self.print_output = print_output + self.debug = debug self.db = self.__init_db(overwrite_db) - def print_it(self, color, text, print_output=True): - if self.print_output: - if color == "red": - print(Fore.RED, text) - elif color == "green": - print(Fore.GREEN, text) - elif color == 'blue': - print(Fore.BLUE, text) - print(Style.RESET_ALL, end='') + def __print(self, color, text): + """ Print function to print colored text """ + if self.debug: + print(colors_dict[color] + text + colors_dict['reset']) def __load_db_from_file(self): + """ Load the database from the file """ with open(self.db_path, 'r') as f: return json.load(f) def __init_db(self, overwrite_db): + """" Initialize the database """ if not overwrite_db and os.path.exists(self.db_path): - self.print_it("green", "Loading database from file") + self.__print("green", "Loading database from file") return self.__load_db_from_file() elif overwrite_db and os.path.exists(self.db_path): - self.print_it("blue", "Overwriting database") + self.__print("blue", "Overwriting database") self.clear() return self.db elif not os.path.exists(self.db_path): - self.print_it("green", "Creating new database") + self.__print("green", "Creating new database") return {} def __dump_db(self, data): + """ Dump the database to the file """ try: with open(self.db_path, 'w+') as f: json.dump(data, f, indent=4) @@ -49,18 +58,18 @@ def __dump_db(self, data): def set(self, key, value, overwrite=False): if key not in self.db: - self.print_it("green", "Key is not present in the database, adding in the database") + self.__print("green", "Key is not present in the database, adding in the database") self.db[key] = value self.__dump_db(self.db) return True elif not overwrite and key in self.db: - self.print_it("red", "Key already exists") + self.__print("red", "Key already exists") return False elif overwrite and key in self.db: - self.print_it("blue", "Key already exists, overwriting the value") + self.__print("blue", "Key already exists, overwriting the value") self.db[key] = value self.__dump_db(self.db) return True @@ -69,16 +78,16 @@ def get(self, key): if key in self.db: return self.db[key] else: - self.print_it("red", "Key not found") + self.__print("red", "Key not found") return False def delete(self, key): if key in self.db: del self.db[key] self.__dump_db(self.db) - self.print_it("green", "Key deleted") + self.__print("green", "Key deleted") else: - self.print_it("red", "Key not found") + self.__print("red", "Key not found") def get_db(self): print(self.db) @@ -87,5 +96,5 @@ def get_db(self): def clear(self): self.db = {} self.__dump_db(self.db) - self.print_it("green", "Database cleared") + self.__print("green", "Database cleared") return True diff --git a/quickdb/tests/test_cases.py b/quickdb/tests/test_cases.py index 13e79b0..ed3c179 100644 --- a/quickdb/tests/test_cases.py +++ b/quickdb/tests/test_cases.py @@ -1,4 +1,7 @@ import unittest +import sys + +sys.path.append(".") from quickdb.main import QuickDB diff --git a/setup.py b/setup.py index 399bc2e..62a1696 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="quickDatabase", - version="0.0.1", + version="0.0.2", author="Deepak Raj", author_email="deepak008@live.com", description="Simple python database", @@ -24,6 +24,6 @@ ], python_requires=">=3.4", entry_points={ - "console_scripts": [], + "console_scripts": ["quickdb=quickdb.cli:main"] }, ) diff --git a/test.sh b/test.sh deleted file mode 100644 index 2fc1136..0000000 --- a/test.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -if ! [ -x "$(command -v flake8)" ]; then - echo 'Error: flake8 is not installed.' >&2 - echo 'Installing flake8...' - pip install flake8 -fi - -if ! [ -x "$(command -v twine)" ]; then - echo 'Error: twine is not installed.' >&2 - echo 'Installing twine...' - pip install twine -fi - -if ! [ -f "setup.py" ]; then - echo 'Error: setup.py is not found.' >&2 - exit 1 -fi - -python3 setup.py bdist sdist bdist_wheel - -if ! [ -d "dist" ]; then - echo 'Error: dist folder is not found.' >&2 - exit 1 -fi - -python3 -m twine upload dist/* - -rm -rf dist -rm -rf build -rm -rf *.egg-info -find . -name "*.pyc" -exec rm -rf {}\; From 8aed693bd28f81fef77f8c742e60db1c85d4a54e Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Sat, 5 Nov 2022 12:46:01 +0530 Subject: [PATCH 05/16] updating docs --- README.md | 2 +- docs/index.rst | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a8ac4c9..7ebf861 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

Quick DB ⚡ 0.0.1

+

Quick DB ⚡ 0.0.2

Light weight database for python, with a simple API and a simple file format. diff --git a/docs/index.rst b/docs/index.rst index 3239007..240e2eb 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -17,3 +17,10 @@ Features - CLI interface - Open source +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + installation.rst + as_command_line.rst + as_module.rst \ No newline at end of file From b3e4916200966bfafc4543fc33c3fc3dc0d8e6f4 Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Fri, 7 Jun 2024 10:26:51 +0530 Subject: [PATCH 06/16] chore: Add support for creating a schema in QuickDB --- .gitignore | 3 +- quickdb/main.py | 68 +++++++++++++++++-------------------- quickdb/tests/test_cases.py | 35 ------------------- tests/test_cases.py | 17 ++++++++++ 4 files changed, 50 insertions(+), 73 deletions(-) delete mode 100644 quickdb/tests/test_cases.py create mode 100644 tests/test_cases.py diff --git a/.gitignore b/.gitignore index 37f8393..c6ba895 100644 --- a/.gitignore +++ b/.gitignore @@ -128,4 +128,5 @@ dmypy.json # Pyre type checker .pyre/ *.json -test_db.py \ No newline at end of file +test_db.py +test.py \ No newline at end of file diff --git a/quickdb/main.py b/quickdb/main.py index 17dbd8b..9550a6b 100644 --- a/quickdb/main.py +++ b/quickdb/main.py @@ -20,25 +20,24 @@ class QuickDB(object): def __init__(self, db_path, overwrite_db=False, debug=True): self.db_path = db_path self.debug = debug - self.db = self.__init_db(overwrite_db) + self.overwrite_db = overwrite_db + self.db = self.__init_db() + self.schema = None + self.primary_key = None + self.primary_value = None def __print(self, color, text): """ Print function to print colored text """ if self.debug: print(colors_dict[color] + text + colors_dict['reset']) - def __load_db_from_file(self): - """ Load the database from the file """ - with open(self.db_path, 'r') as f: - return json.load(f) - - def __init_db(self, overwrite_db): + def __init_db(self): """" Initialize the database """ - if not overwrite_db and os.path.exists(self.db_path): + if not self.overwrite_db and os.path.exists(self.db_path): self.__print("green", "Loading database from file") return self.__load_db_from_file() - elif overwrite_db and os.path.exists(self.db_path): + elif self.overwrite_db and os.path.exists(self.db_path): self.__print("blue", "Overwriting database") self.clear() return self.db @@ -46,6 +45,19 @@ def __init_db(self, overwrite_db): elif not os.path.exists(self.db_path): self.__print("green", "Creating new database") return {} + + def create_schema(self, columns_list, primary_key): + """ Create the schema of the database """ + self.schema = { + "columns": columns_list, + "primary_key": primary_key + } + self.primary_key = primary_key + + def __load_db_from_file(self): + """ Load the database from the file """ + with open(self.db_path, 'r') as f: + return json.load(f) def __dump_db(self, data): """ Dump the database to the file """ @@ -56,41 +68,23 @@ def __dump_db(self, data): except Exception: return False - def set(self, key, value, overwrite=False): - if key not in self.db: - self.__print("green", "Key is not present in the database, adding in the database") + def set(self, value, overwrite=False): + """ Set the key-value pair in the database """ + primary_value = value[self.schema["columns"].index(self.primary_key)] - self.db[key] = value - self.__dump_db(self.db) - return True - - elif not overwrite and key in self.db: + if primary_value in self.db and not overwrite: self.__print("red", "Key already exists") return False - - elif overwrite and key in self.db: - self.__print("blue", "Key already exists, overwriting the value") - self.db[key] = value - self.__dump_db(self.db) - return True - - def get(self, key): - if key in self.db: - return self.db[key] - else: - self.__print("red", "Key not found") + + if self.primary_key not in self.schema["columns"] or len(value) != len(self.schema["columns"]): + self.__print("red", "Invalid column name or number of columns") return False - def delete(self, key): - if key in self.db: - del self.db[key] - self.__dump_db(self.db) - self.__print("green", "Key deleted") - else: - self.__print("red", "Key not found") + self.db[primary_value] = dict(zip(self.schema["columns"], value)) + self.__dump_db(self.db) + return True def get_db(self): - print(self.db) return self.db def clear(self): diff --git a/quickdb/tests/test_cases.py b/quickdb/tests/test_cases.py deleted file mode 100644 index ed3c179..0000000 --- a/quickdb/tests/test_cases.py +++ /dev/null @@ -1,35 +0,0 @@ -import unittest -import sys - -sys.path.append(".") - -from quickdb.main import QuickDB - -db = QuickDB("test_db.json", overwrite_db=True) - - -class DatabaseTest(unittest.TestCase): - - def test_operation_one(self): - """ if key does not exist, it should be added """ - self.assertTrue(db.set("name", "john")) - self.assertTrue(db.set("age", 25)) - self.assertTrue(db.set("age", 30, overwrite=True)) - self.assertEqual(db.get_db(), {'name': 'john', 'age': 30}) - self.assertTrue(db.clear(), True) - - def test_operation_two(self): - """ if key already exists, it should not be added """ - self.assertTrue(db.set("name", "john")) - self.assertFalse(db.set("name", "john")) - self.assertTrue(db.clear(), True) - - def test_operation_three(self): - """ if key already exists, it should be overwritten """ - self.assertTrue(db.set("name", "john")) - self.assertTrue(db.set("name", "john", overwrite=True)) - self.assertTrue(db.clear(), True) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/test_cases.py b/tests/test_cases.py new file mode 100644 index 0000000..e500d1b --- /dev/null +++ b/tests/test_cases.py @@ -0,0 +1,17 @@ +import unittest +import sys + +sys.path.append(".") + +from quickdb.main import QuickDB + +db = QuickDB("test_db.json", overwrite_db=True) + + +class DatabaseTest(unittest.TestCase): + pass + + + +if __name__ == '__main__': + unittest.main() From b7d75ffd14354f0e7b4876e96967502cb6316abf Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:09:10 +0530 Subject: [PATCH 07/16] feat: Add support for `schema` and `table` in `Database` class --- CHANGELOG.md | 5 +++++ quickdb/main.py | 60 +++++++++++++++---------------------------------- 2 files changed, 23 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91c0acf..9fb6412 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Version 0.0.2 + +- Added support for `schema` and `table` in `Database` class + ## [Initial Release] - Initial release with basic database features++ - Initial documentation++ - Initial tests++ + diff --git a/quickdb/main.py b/quickdb/main.py index 9550a6b..e2109e3 100644 --- a/quickdb/main.py +++ b/quickdb/main.py @@ -3,17 +3,6 @@ from colorama import Fore, Style -colors_dict = { - 'red' : Fore.RED, - 'green' : Fore.GREEN, - 'yellow' : Fore.YELLOW, - 'blue' : Fore.BLUE, - 'magenta' : Fore.MAGENTA, - 'cyan' : Fore.CYAN, - 'white' : Fore.WHITE, - 'reset' : Style.RESET_ALL -} - class QuickDB(object): """ python database.py """ @@ -26,38 +15,22 @@ def __init__(self, db_path, overwrite_db=False, debug=True): self.primary_key = None self.primary_value = None - def __print(self, color, text): - """ Print function to print colored text """ - if self.debug: - print(colors_dict[color] + text + colors_dict['reset']) + def __load_db_from_file(self): + """ Load the database from the file """ + with open(self.db_path, 'r') as f: + return json.load(f) def __init_db(self): """" Initialize the database """ + if not self.overwrite_db and os.path.exists(self.db_path): - self.__print("green", "Loading database from file") return self.__load_db_from_file() - - elif self.overwrite_db and os.path.exists(self.db_path): - self.__print("blue", "Overwriting database") + + if self.overwrite_db and os.path.exists(self.db_path): self.clear() return self.db - elif not os.path.exists(self.db_path): - self.__print("green", "Creating new database") - return {} - - def create_schema(self, columns_list, primary_key): - """ Create the schema of the database """ - self.schema = { - "columns": columns_list, - "primary_key": primary_key - } - self.primary_key = primary_key - - def __load_db_from_file(self): - """ Load the database from the file """ - with open(self.db_path, 'r') as f: - return json.load(f) + return {} def __dump_db(self, data): """ Dump the database to the file """ @@ -65,22 +38,26 @@ def __dump_db(self, data): with open(self.db_path, 'w+') as f: json.dump(data, f, indent=4) return True - except Exception: + except json.JSONDecodeError: return False + + def create_schema(self, columns_list, primary_key): + """ Create the schema of the database """ + self.primary_key = primary_key + self.columns_list = columns_list + self.primary_value_index = self.columns_list.index(self.primary_key) def set(self, value, overwrite=False): """ Set the key-value pair in the database """ - primary_value = value[self.schema["columns"].index(self.primary_key)] + primary_value = value[self.primary_value_index] if primary_value in self.db and not overwrite: - self.__print("red", "Key already exists") return False - if self.primary_key not in self.schema["columns"] or len(value) != len(self.schema["columns"]): - self.__print("red", "Invalid column name or number of columns") + if self.primary_key not in self.columns_list or len(value) != len(self.columns_list): return False - self.db[primary_value] = dict(zip(self.schema["columns"], value)) + self.db[primary_value] = dict(zip(self.columns_list, value)) self.__dump_db(self.db) return True @@ -90,5 +67,4 @@ def get_db(self): def clear(self): self.db = {} self.__dump_db(self.db) - self.__print("green", "Database cleared") return True From c32bcb4870663550f715ea81ef46846d18f9fa93 Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:47:50 +0530 Subject: [PATCH 08/16] chore: Remove deprecated command line interface (CLI) code and update documentation --- .readthedocs.yaml | 24 ++++++++++++++++++++ docs/as_command_line.rst | 42 ----------------------------------- docs/conf.py | 2 +- docs/index.rst | 7 ++---- docs/installation.rst | 9 ++++++++ quickdb/cli.py | 48 ---------------------------------------- scripts/README.md | 11 +++++++++ scripts/code_coverage.sh | 17 ++++++++++++++ scripts/release.sh | 36 ++++++++++++++++++++++++++++++ scripts/test_changes.sh | 27 ++++++++++++++++++++++ scripts/test_release.sh | 36 ++++++++++++++++++++++++++++++ 11 files changed, 163 insertions(+), 96 deletions(-) create mode 100644 .readthedocs.yaml delete mode 100644 docs/as_command_line.rst delete mode 100644 quickdb/cli.py create mode 100644 scripts/README.md create mode 100644 scripts/code_coverage.sh create mode 100644 scripts/release.sh create mode 100644 scripts/test_changes.sh create mode 100644 scripts/test_release.sh diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..3e856e9 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,24 @@ +# Read the Docs configuration file for Sphinx projects +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.12" + +# Build documentation in the "docs/" directory with Sphinx +sphinx: + configuration: docs/conf.py + +# Optionally build your docs in additional formats such as PDF and ePub +formats: + - pdf + - epub + +python: + install: + - requirements: docs/requirements.txt \ No newline at end of file diff --git a/docs/as_command_line.rst b/docs/as_command_line.rst deleted file mode 100644 index 1918a06..0000000 --- a/docs/as_command_line.rst +++ /dev/null @@ -1,42 +0,0 @@ -Command line Usages -================== - -.. code-block:: bash - - --debug Enable debug mode - -v, --version show program's version number and exit - -p path to the database - - -s SET, --set SET Set a key-value pair in the database - -g GET, --get GET Get a value from the database - -d DELETE, --delete DELETE - Delete a key-value pair from the database - -c, --clear Clear the database - - -o --overwrite to overwrite the value if the key already exists - -Set a key-value pair in the database - -.. code-block:: bash - quickdb -p test.db -s key=value - - # if the key already exists, overwrite the value by adding the -o flag - quickdb -p test.db -s key=value -o - -Get a value from the database - -.. code-block:: bash - quickdb -p test.db -g key - -Delete a key-value pair from the database - -.. code-block:: bash - quickdb -p test.db -d key - - -Clear the database - -.. code-block:: bash - quickdb -p test.db -c - -use --debug to enable debug mode with colored output diff --git a/docs/conf.py b/docs/conf.py index 8e69d8d..cd5c007 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,7 +1,7 @@ from datetime import datetime project = 'quickDB' -release = '0.0.1' +release = '0.0.2' templates_path = ['_templates'] source_suffix = ".rst" master_doc = "index" diff --git a/docs/index.rst b/docs/index.rst index 240e2eb..569c188 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,15 +12,12 @@ Features -------- - Simple API -- CLI support with colorful output - Easy to use -- CLI interface - Open source .. toctree:: :maxdepth: 2 :caption: Contents: - installation.rst - as_command_line.rst - as_module.rst \ No newline at end of file + installation.rst + as_module.rst \ No newline at end of file diff --git a/docs/installation.rst b/docs/installation.rst index 32cce5a..257463f 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -17,4 +17,13 @@ Install Via Source(Unreleased/latest) cd quickdb python setup.py install +Why QuickDB? +------------ + +QuickDB is a light weight database for python, with a simple API and a simple file format. It is not meant to be a full +featured database, but rather a simple way to store data in a file. It's written in python, and is compatible with python +3.6 and above. The main goal of QuickDB is to provide a simple, faster and easy to use database for python developers. + + + \ No newline at end of file diff --git a/quickdb/cli.py b/quickdb/cli.py deleted file mode 100644 index 2c3e1b3..0000000 --- a/quickdb/cli.py +++ /dev/null @@ -1,48 +0,0 @@ -import argparse -import sys - -sys.path.append(".") -from quickdb import QuickDB - -version = "quickdb 0.0.2" - -argparse = argparse.ArgumentParser(description="QuickDB CLI") -argparse.add_argument("--debug", action="store_true", help="Enable debug mode") -argparse.add_argument("-p", "--db_path", help="Path to the database file", required=True) -argparse.add_argument("-o", "--overwrite", help="Overwrite the database", action="store_true") -argparse.add_argument('-v', '--version', action='version', version=version) - -group = argparse.add_mutually_exclusive_group(required=True) -group.add_argument("-s", "--set", help="Set a key-value pair in the database") -group.add_argument("-g", "--get", help="Get a value from the database") -group.add_argument("-d", "--delete", help="Delete a key-value pair from the database") -group.add_argument("-c", "--clear", help="Clear the database", action="store_true") -args = argparse.parse_args() - -debug = True if args.debug else False - -db = QuickDB(args.db_path, overwrite_db=False, debug=debug) - - -def main(): - if args.set: - key, value = args.set.split("=") - if args.overwrite: - db.set(key, value, overwrite=True) - else: - db.set(key, value) - elif args.get: - key = args.get - print(db.get(key)) - elif args.delete: - key = args.delete - db.delete(key) - elif args.clear: - db.clear() - else: - print("Invalid arguments") - # check if the command is similar to any of the commands - - -if __name__ == "__main__": - main() diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..e8fe103 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,11 @@ +# Scripts + +1. test_changes.sh - Test if the changes are valid and can be released. flake8/pytest are run and the version is checked. +2. code_coverage.sh - Run the tests and generate a code coverage report. +3. test_release.sh - Test the release on test.pypi.org. +4. release.sh - Release the package to PyPI if both tests are successful. + + +reference links: + +- https://packaging.python.org/en/latest/guides/using-testpypi/ diff --git a/scripts/code_coverage.sh b/scripts/code_coverage.sh new file mode 100644 index 0000000..1ad60ee --- /dev/null +++ b/scripts/code_coverage.sh @@ -0,0 +1,17 @@ +#!/bin/bash +check_command() { + if [ ! -x "$(command -v $1)" ]; then + echo "$1 is not installed" + pip install $1 + exit 1 + fi +} + +check_command coverage +check_command pytest + +coverage run -m pytest +coverage report -> coverage.txt + + + diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100644 index 0000000..7d7fc54 --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,36 @@ +#!/bin/bash +check_command() { + if [ ! -x "$(command -v $1)" ]; then + echo "$1 is not installed" + pip install $1 + exit 1 + fi +} + +check_directory() { + if [ ! -d "$1" ]; then + echo "$1 is not found" + exit 1 + fi +} + +check_file() { + if [ ! -f "$1" ]; then + echo "$1 is not found" + exit 1 + fi +} + +# check if the git is installed +check_command git +check_command flake8 +check_command twine +check_file setup.py +python3 setup.py sdist bdist_wheel +check_directory dist +python3 -m twine upload dist/* + +rm -rf dist +rm -rf build +rm -rf *.egg-info +find . -name "*.pyc" -exec rm -rf {}\; diff --git a/scripts/test_changes.sh b/scripts/test_changes.sh new file mode 100644 index 0000000..565a414 --- /dev/null +++ b/scripts/test_changes.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +# function to check the command exist or not +check_command() { + if [ ! -x "$(command -v $1)" ]; then + echo "$1 is not installed" + pip install $1 + exit 1 + fi +} + +# check if the git is installed +check_command git +check_command pytest +check_command flake8 + +flake8 . --isolated --exclude=.cache,.venv,.svn,CVS,.bzr,.hg,.git,__pycache__,.tox,**/migrations/** --ignore=E501,E402 +pytest + +# check the exit code of the last command +if [ $? -eq 0 ]; then + echo "All tests passed" +else + echo "Some tests failed" + exit 1 +fi + diff --git a/scripts/test_release.sh b/scripts/test_release.sh new file mode 100644 index 0000000..58e8161 --- /dev/null +++ b/scripts/test_release.sh @@ -0,0 +1,36 @@ +#!/bin/bash +check_command() { + if [ ! -x "$(command -v $1)" ]; then + echo "$1 is not installed" + pip install $1 + exit 1 + fi +} + +check_directory() { + if [ ! -d "$1" ]; then + echo "$1 is not found" + exit 1 + fi +} + +check_file() { + if [ ! -f "$1" ]; then + echo "$1 is not found" + exit 1 + fi +} + +# check if the git is installed +check_command git +check_command flake8 +check_command twine +check_file ./setup.py +python setup.py sdist bdist_wheel +check_directory dist +python -m twine upload --repository testpypi dist/* + +rm -rf dist +rm -rf build +rm -rf *.egg-info +find . -name "*.pyc" -exec rm -rf {}\; From 5b1cf0423511e5e65f71c1cb06922d6dfc28c746 Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Sat, 8 Jun 2024 09:24:38 +0530 Subject: [PATCH 09/16] chore: Refactor QuickDB class to improve code structure and readability --- quickdb/main.py | 85 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 16 deletions(-) diff --git a/quickdb/main.py b/quickdb/main.py index e2109e3..1538e8f 100644 --- a/quickdb/main.py +++ b/quickdb/main.py @@ -1,18 +1,16 @@ import os import json -from colorama import Fore, Style - -class QuickDB(object): +class QuickDB: """ python database.py """ - def __init__(self, db_path, overwrite_db=False, debug=True): + def __init__(self, db_path="db.json", overwrite_db=False, debug=True): self.db_path = db_path self.debug = debug self.overwrite_db = overwrite_db self.db = self.__init_db() - self.schema = None self.primary_key = None + self.primary_value_index = None self.primary_value = None def __load_db_from_file(self): @@ -32,39 +30,94 @@ def __init_db(self): return {} - def __dump_db(self, data): + def dump_db(self): """ Dump the database to the file """ try: with open(self.db_path, 'w+') as f: - json.dump(data, f, indent=4) + json.dump(self.db, f, indent=4) return True except json.JSONDecodeError: return False - def create_schema(self, columns_list, primary_key): + def create_table(self, columns_list, primary_key=None): """ Create the schema of the database """ self.primary_key = primary_key self.columns_list = columns_list + if primary_key not in columns_list: + raise ValueError(f"Primary key {primary_key} not in columns list") self.primary_value_index = self.columns_list.index(self.primary_key) - def set(self, value, overwrite=False): + self.schema = { + "columns_list": self.columns_list, + "primary_key": self.primary_key, + "primary_value_index": self.primary_value_index + } + + self.db['schema'] = self.schema + self.dump_db() + + def get_table(self): + return self.db['schema'] + + def insert(self, value, overwrite=False, dump_db=False): """ Set the key-value pair in the database """ - primary_value = value[self.primary_value_index] + primary_value = str(value[self.primary_value_index]) - if primary_value in self.db and not overwrite: + if primary_value in self.db['database'] and not overwrite: return False - if self.primary_key not in self.columns_list or len(value) != len(self.columns_list): + if len(value) != len(self.columns_list): return False + + self.db["database"][primary_value] = dict(zip(self.columns_list, value)) - self.db[primary_value] = dict(zip(self.columns_list, value)) - self.__dump_db(self.db) + if dump_db: + self.dump_db() return True def get_db(self): return self.db def clear(self): - self.db = {} - self.__dump_db(self.db) + self.db = {"database": {}, "schema": {}} + self.dump_db() return True + + def delete(self, primary_value): + """ Delete the key-value pair in the database """ + if primary_value in self.db['database']: + del self.db['database'][primary_value] + self.dump_db() + return True + return False + + def update(self, primary_value, value): + """ Update the key-value pair in the database """ + if primary_value in self.db['database']: + self.db['database'][primary_value] = value + self.dump_db() + return True + return False + + def search(self, primary_value): + """ Search the key-value pair in the database """ + if primary_value in self.db['database']: + return self.db['database'][primary_value] + return False + + def where(self, column_name, value): + """ Search the key-value pair in the database """ + result = [] + for key, val in self.db['database'].items(): + if val[column_name] == value: + result.append(val) + return result + + def __repr__(self): + return f"QuickDB(db_path={self.db_path}, db={self.db})" + + def __str__(self): + return f"QuickDB(db_path={self.db_path}, db={self.db})" + + def __getitem__(self, key): + return self.db["database"][key] if key in self.db["database"] else None \ No newline at end of file From 37570deb985301e6d5dfeee26cc15bf5f3bf1366 Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Thu, 13 Jun 2024 07:34:17 +0530 Subject: [PATCH 10/16] chore: Update .gitignore and add support for logger and multiple tables in QuickDB --- .gitignore | 4 +- CHANGELOG.md | 5 ++ quickdb/__init__.py | 2 +- quickdb/main.py | 162 ++++++++++++++++++++++++++++++++++---------- 4 files changed, 135 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index c6ba895..9e60762 100644 --- a/.gitignore +++ b/.gitignore @@ -129,4 +129,6 @@ dmypy.json .pyre/ *.json test_db.py -test.py \ No newline at end of file +test.py +*.log +quick_db_output/ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fb6412..857250d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format ## Version 0.0.2 - Added support for `schema` and `table` in `Database` class +- Support for logger added +- Support for multiple tables in a database added +- Support for drop table added +- Support for drop database added +- Support for `select` , `insert`, `update` and `delete` queries added ## [Initial Release] diff --git a/quickdb/__init__.py b/quickdb/__init__.py index 2471f9f..73329fd 100644 --- a/quickdb/__init__.py +++ b/quickdb/__init__.py @@ -1,3 +1,3 @@ from quickdb.main import QuickDB -__all__ = ['QuickDB'] +__all__ = ["QuickDB"] \ No newline at end of file diff --git a/quickdb/main.py b/quickdb/main.py index 1538e8f..b96c7af 100644 --- a/quickdb/main.py +++ b/quickdb/main.py @@ -1,18 +1,39 @@ import os import json +import pandas as pd +import logging -class QuickDB: +class Logger: + """ Logger class to log the messages """ + def __init__(self, log_path): + self.log_path = log_path + self.logger = logging.getLogger(__name__) + + logging.basicConfig(filename=self.log_path, + level=logging.INFO, + format='%(asctime)s:%(levelname)s:%(lineno)d:%(message)s', + datefmt='%Y-%m-%d %H:%M:%S', + filemode='a') + self.logger.info(f"Logger initialized with log path {self.log_path}") + + +class QuickDB(Logger): """ python database.py """ - def __init__(self, db_path="db.json", overwrite_db=False, debug=True): + def __init__(self, db_path="db.json", db_drop_path="quick_db_output", + overwrite_db=False, debug=True, db_log_path="dedug.log"): + super().__init__(db_log_path) + """ Initialize the database """ + self.db_path = db_path self.debug = debug self.overwrite_db = overwrite_db self.db = self.__init_db() - self.primary_key = None - self.primary_value_index = None - self.primary_value = None - + self.schema = self.db['schema'] + self.database = self.db['database'] + self.db_drop_path = db_drop_path + self.db_log_path = db_log_path + def __load_db_from_file(self): """ Load the database from the file """ with open(self.db_path, 'r') as f: @@ -22,13 +43,16 @@ def __init_db(self): """" Initialize the database """ if not self.overwrite_db and os.path.exists(self.db_path): + self.logger.info(f"Loading database from {self.db_path}") return self.__load_db_from_file() if self.overwrite_db and os.path.exists(self.db_path): + self.logger.info(f"Overwriting database from {self.db_path}") self.clear() return self.db - return {} + self.logger.info(f"Creating new database at {self.db_path}") + return {"database": {}, "schema": {}} def dump_db(self): """ Dump the database to the file """ @@ -38,77 +62,143 @@ def dump_db(self): return True except json.JSONDecodeError: return False + + def dumb_table(self, table_name, output_format='json'): + """ Dump the table to the file """ + if table_name not in self.db['database']: + return False + + os.makedirs(self.db_drop_path, exist_ok=True) + + table_data = self.db['database'][table_name] + + if output_format == 'json': + with open(os.path.join(self.db_drop_path, f"{table_name}.json"), 'w+') as f: + json.dump(table_data, f, indent=4) + self.logger.info(f"Table {table_name} dumped to {table_name}.json") + return True + + if output_format == 'csv': + df = pd.DataFrame(table_data).T + df.to_csv(os.path.join(self.db_drop_path, f"{table_name}.csv"), index=False) + self.logger.info(f"Table {table_name} dumped to {table_name}.csv") + return True + + if output_format == 'excel': + df = pd.DataFrame(table_data) + df.to_excel(os.path.join(self.db_drop_path, f"{table_name}.xlsx"), index=False) + self.logger.info(f"Table {table_name} dumped to {table_name}.xlsx") + return True + + if output_format == 'df': + return pd.DataFrame(table_data) + + if output_format == 'print': + print(table_data) + return True - def create_table(self, columns_list, primary_key=None): + def create_table(self, table_name, columns_list, primary_key=None): """ Create the schema of the database """ - self.primary_key = primary_key - self.columns_list = columns_list + if primary_key not in columns_list: raise ValueError(f"Primary key {primary_key} not in columns list") - self.primary_value_index = self.columns_list.index(self.primary_key) - - self.schema = { - "columns_list": self.columns_list, - "primary_key": self.primary_key, - "primary_value_index": self.primary_value_index + + primary_key_index = columns_list.index(primary_key) + + self.schema[table_name] = { + "columns_list": columns_list, + "primary_key": primary_key, + "primary_key_index": primary_key_index } self.db['schema'] = self.schema + self.db['database'][table_name] = {} + self.logger.info(f"Table {table_name} created with columns {columns_list} and primary key {primary_key}") self.dump_db() - def get_table(self): - return self.db['schema'] + def get_table_names(self): + """ Get all the tables in the database""" + return list(self.schema.keys()) + + def get_table(self, table_name): + """ Get the table schema """ + return self.schema[table_name] + + def get_table_columns(self, table_name): + """ Get the columns of the table """ + return self.schema[table_name]['columns_list'] - def insert(self, value, overwrite=False, dump_db=False): + def get_table_primary_key(self, table_name): + """ Get the primary key of the table """ + return self.schema[table_name]['primary_key'] + + def insert_into(self, table_name, value, overwrite=False, dump_db=False): """ Set the key-value pair in the database """ - primary_value = str(value[self.primary_value_index]) + primary_value = value[self.schema[table_name]['primary_key_index']] + columns_list = self.schema[table_name]['columns_list'] - if primary_value in self.db['database'] and not overwrite: + if primary_value in self.db['database'][table_name] and not overwrite: return False - if len(value) != len(self.columns_list): + if len(value) != len(columns_list): return False - self.db["database"][primary_value] = dict(zip(self.columns_list, value)) + self.db["database"][table_name][primary_value] = dict(zip(columns_list, value)) + self.logger.info(f"Inserted {value} into {table_name}") if dump_db: self.dump_db() return True def get_db(self): + """ Get the database along with the schema """ return self.db def clear(self): + """ Clear the database """ self.db = {"database": {}, "schema": {}} self.dump_db() + self.logger.info("Database cleared") return True - - def delete(self, primary_value): + + def drop_table(self, table_name): + """ Drop the table from the database """ + if table_name in self.db['database']: + del self.db['database'][table_name] + del self.db['schema'][table_name] + self.dump_db() + self.logger.info(f"Table {table_name} dropped") + return True + return False + + def delete(self, table_name, primary_value): """ Delete the key-value pair in the database """ - if primary_value in self.db['database']: - del self.db['database'][primary_value] + if primary_value in self.db['database'][table_name]: + del self.db['database'][table_name][primary_value] self.dump_db() + self.logger.info(f"Deleted {primary_value} from {table_name}") return True return False - def update(self, primary_value, value): + def update(self, table_name, primary_value, value): """ Update the key-value pair in the database """ - if primary_value in self.db['database']: - self.db['database'][primary_value] = value + if primary_value in self.db['database'][table_name]: + self.db['database'][table_name][primary_value] = value self.dump_db() + self.logger.info(f"Updated {primary_value} in {table_name}") return True return False - def search(self, primary_value): + def search(self, table_name, primary_value): """ Search the key-value pair in the database """ - if primary_value in self.db['database']: - return self.db['database'][primary_value] + if primary_value in self.db['database'][table_name]: + return self.db['database'][table_name][primary_value] return False - def where(self, column_name, value): + def where(self, table_name, column_name, value): """ Search the key-value pair in the database """ result = [] - for key, val in self.db['database'].items(): + for key, val in self.db['database'][table_name].items(): if val[column_name] == value: result.append(val) return result @@ -120,4 +210,4 @@ def __str__(self): return f"QuickDB(db_path={self.db_path}, db={self.db})" def __getitem__(self, key): - return self.db["database"][key] if key in self.db["database"] else None \ No newline at end of file + return self.db["database"][key] if key in self.db["database"] else None From 58a1c23ffa3a14759651f2c9a3ce512ae2427a11 Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Thu, 13 Jun 2024 07:38:50 +0530 Subject: [PATCH 11/16] chore: formatted by flake8 --- CHANGELOG.md | 2 +- quickdb/__init__.py | 2 +- quickdb/main.py | 50 ++++++++++++++++++++++----------------------- tests/test_cases.py | 1 - 4 files changed, 27 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 857250d..4e67e92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ All notable changes to this project will be documented in this file. The format - Support for drop database added - Support for `select` , `insert`, `update` and `delete` queries added -## [Initial Release] +## [Initial Release] Version 0.0.1 - Initial release with basic database features++ - Initial documentation++ diff --git a/quickdb/__init__.py b/quickdb/__init__.py index 73329fd..7ee5dc5 100644 --- a/quickdb/__init__.py +++ b/quickdb/__init__.py @@ -1,3 +1,3 @@ from quickdb.main import QuickDB -__all__ = ["QuickDB"] \ No newline at end of file +__all__ = ["QuickDB"] diff --git a/quickdb/main.py b/quickdb/main.py index b96c7af..62a9ad1 100644 --- a/quickdb/main.py +++ b/quickdb/main.py @@ -10,9 +10,9 @@ def __init__(self, log_path): self.log_path = log_path self.logger = logging.getLogger(__name__) - logging.basicConfig(filename=self.log_path, + logging.basicConfig(filename=self.log_path, level=logging.INFO, - format='%(asctime)s:%(levelname)s:%(lineno)d:%(message)s', + format='%(asctime)s:%(levelname)s:%(lineno)d:%(message)s', datefmt='%Y-%m-%d %H:%M:%S', filemode='a') self.logger.info(f"Logger initialized with log path {self.log_path}") @@ -20,7 +20,7 @@ def __init__(self, log_path): class QuickDB(Logger): """ python database.py """ - def __init__(self, db_path="db.json", db_drop_path="quick_db_output", + def __init__(self, db_path="db.json", db_drop_path="quick_db_output", overwrite_db=False, debug=True, db_log_path="dedug.log"): super().__init__(db_log_path) """ Initialize the database """ @@ -33,7 +33,7 @@ def __init__(self, db_path="db.json", db_drop_path="quick_db_output", self.database = self.db['database'] self.db_drop_path = db_drop_path self.db_log_path = db_log_path - + def __load_db_from_file(self): """ Load the database from the file """ with open(self.db_path, 'r') as f: @@ -45,7 +45,7 @@ def __init_db(self): if not self.overwrite_db and os.path.exists(self.db_path): self.logger.info(f"Loading database from {self.db_path}") return self.__load_db_from_file() - + if self.overwrite_db and os.path.exists(self.db_path): self.logger.info(f"Overwriting database from {self.db_path}") self.clear() @@ -62,12 +62,12 @@ def dump_db(self): return True except json.JSONDecodeError: return False - + def dumb_table(self, table_name, output_format='json'): """ Dump the table to the file """ if table_name not in self.db['database']: return False - + os.makedirs(self.db_drop_path, exist_ok=True) table_data = self.db['database'][table_name] @@ -95,16 +95,16 @@ def dumb_table(self, table_name, output_format='json'): if output_format == 'print': print(table_data) - return True - + return True + def create_table(self, table_name, columns_list, primary_key=None): """ Create the schema of the database """ if primary_key not in columns_list: raise ValueError(f"Primary key {primary_key} not in columns list") - + primary_key_index = columns_list.index(primary_key) - + self.schema[table_name] = { "columns_list": columns_list, "primary_key": primary_key, @@ -119,19 +119,19 @@ def create_table(self, table_name, columns_list, primary_key=None): def get_table_names(self): """ Get all the tables in the database""" return list(self.schema.keys()) - + def get_table(self, table_name): """ Get the table schema """ return self.schema[table_name] - + def get_table_columns(self, table_name): """ Get the columns of the table """ return self.schema[table_name]['columns_list'] - + def get_table_primary_key(self, table_name): """ Get the primary key of the table """ return self.schema[table_name]['primary_key'] - + def insert_into(self, table_name, value, overwrite=False, dump_db=False): """ Set the key-value pair in the database """ primary_value = value[self.schema[table_name]['primary_key_index']] @@ -139,10 +139,10 @@ def insert_into(self, table_name, value, overwrite=False, dump_db=False): if primary_value in self.db['database'][table_name] and not overwrite: return False - + if len(value) != len(columns_list): return False - + self.db["database"][table_name][primary_value] = dict(zip(columns_list, value)) self.logger.info(f"Inserted {value} into {table_name}") @@ -160,7 +160,7 @@ def clear(self): self.dump_db() self.logger.info("Database cleared") return True - + def drop_table(self, table_name): """ Drop the table from the database """ if table_name in self.db['database']: @@ -170,7 +170,7 @@ def drop_table(self, table_name): self.logger.info(f"Table {table_name} dropped") return True return False - + def delete(self, table_name, primary_value): """ Delete the key-value pair in the database """ if primary_value in self.db['database'][table_name]: @@ -179,7 +179,7 @@ def delete(self, table_name, primary_value): self.logger.info(f"Deleted {primary_value} from {table_name}") return True return False - + def update(self, table_name, primary_value, value): """ Update the key-value pair in the database """ if primary_value in self.db['database'][table_name]: @@ -188,13 +188,13 @@ def update(self, table_name, primary_value, value): self.logger.info(f"Updated {primary_value} in {table_name}") return True return False - + def search(self, table_name, primary_value): """ Search the key-value pair in the database """ if primary_value in self.db['database'][table_name]: return self.db['database'][table_name][primary_value] return False - + def where(self, table_name, column_name, value): """ Search the key-value pair in the database """ result = [] @@ -202,12 +202,12 @@ def where(self, table_name, column_name, value): if val[column_name] == value: result.append(val) return result - + def __repr__(self): return f"QuickDB(db_path={self.db_path}, db={self.db})" - + def __str__(self): return f"QuickDB(db_path={self.db_path}, db={self.db})" - + def __getitem__(self, key): return self.db["database"][key] if key in self.db["database"] else None diff --git a/tests/test_cases.py b/tests/test_cases.py index e500d1b..39de25c 100644 --- a/tests/test_cases.py +++ b/tests/test_cases.py @@ -12,6 +12,5 @@ class DatabaseTest(unittest.TestCase): pass - if __name__ == '__main__': unittest.main() From ba9e7dde3d3062f7273db6fa86ed964f2c741dd2 Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Thu, 13 Jun 2024 08:36:01 +0530 Subject: [PATCH 12/16] feat: version 0.0.3 released --- CHANGELOG.md | 6 +++++- README.md | 2 +- docs/as_module.rst | 54 ++++++++++++++++++++++++++++++++++++++++++++++ docs/conf.py | 2 +- quickdb/main.py | 23 ++++++++++++++++++-- requirements.txt | 2 +- setup.py | 2 +- 7 files changed, 84 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e67e92..c74f429 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Version 0.0.3 + +- Support for multi insert queries added +- `dum_db` parameter changed to `commit` in insert queries + ## Version 0.0.2 - Added support for `schema` and `table` in `Database` class - Support for logger added - Support for multiple tables in a database added - Support for drop table added -- Support for drop database added - Support for `select` , `insert`, `update` and `delete` queries added ## [Initial Release] Version 0.0.1 diff --git a/README.md b/README.md index 7ebf861..2199296 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

Quick DB ⚡ 0.0.2

+

Quick DB ⚡ 0.0.3

Light weight database for python, with a simple API and a simple file format. diff --git a/docs/as_module.rst b/docs/as_module.rst index e69de29..067582c 100644 --- a/docs/as_module.rst +++ b/docs/as_module.rst @@ -0,0 +1,54 @@ +Use as library +============== + +``` +from quickdb import QuickDB +``` + +Initialize the database +------------------------ + +``` +db_object = QuickDB(db_path="quickdb.json") +``` + +Create a table +-------------- + +It will create a table schema with the given columns and primary key. +If the table already exists, it will not create a new table. + +``` +table_name = 'employee' +columns = ['serial', 'name', 'age', 'city', 'country', 'email', 'phone', 'salary'] +primary_key = 'serial' +db_object.create_table(table_name, columns, primary_key) +``` + +Insert data +----------- + +It will insert the data into the table. if primary_key is already present, it will not insert the data. +overwrite need to pass as True to overwrite the data. + +``` +db_object.insert_into(table_name=table_name, + value=[1, 'John Doe', 30, 'New York', 'USA', 'john@gmail.com', '1234567890', 50000], commit=True) +db_object.insert_into(table_name=table_name, + value=[1, 'John Doe', 30, 'New York', 'USA', 'john@gmail.com', '1234567890', 50000], commit=True, overwrite=True) +db_object.dump_db() # Save the data to the file +``` + +Insert multiple data +-------------------- + +If you want to insert multiple data at once, you can use the below method. + +``` +# insert_into_many +values = [ + [3, 'John Doe', 30, 'New York', 'USA', 'd@gmail.com', '1234567890', 50000], + [4, 'John Doe', 30, 'New York', 'USA', 'f@gs', '1234567890', 50000] +] +db_object.insert_into_many(table_name=table_name, values=values, commit=True) +``` diff --git a/docs/conf.py b/docs/conf.py index cd5c007..f6ddd6e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,7 +1,7 @@ from datetime import datetime project = 'quickDB' -release = '0.0.2' +release = '0.0.3' templates_path = ['_templates'] source_suffix = ".rst" master_doc = "index" diff --git a/quickdb/main.py b/quickdb/main.py index 62a9ad1..73937eb 100644 --- a/quickdb/main.py +++ b/quickdb/main.py @@ -132,7 +132,7 @@ def get_table_primary_key(self, table_name): """ Get the primary key of the table """ return self.schema[table_name]['primary_key'] - def insert_into(self, table_name, value, overwrite=False, dump_db=False): + def insert_into(self, table_name, value, overwrite=False, commit=False): """ Set the key-value pair in the database """ primary_value = value[self.schema[table_name]['primary_key_index']] columns_list = self.schema[table_name]['columns_list'] @@ -146,7 +146,26 @@ def insert_into(self, table_name, value, overwrite=False, dump_db=False): self.db["database"][table_name][primary_value] = dict(zip(columns_list, value)) self.logger.info(f"Inserted {value} into {table_name}") - if dump_db: + if commit: + self.dump_db() + return True + + def insert_into_many(self, table_name, values, overwrite=False, commit=False): + """ Set the key-value pair in the database """ + for value in values: + primary_value = value[self.schema[table_name]['primary_key_index']] + columns_list = self.schema[table_name]['columns_list'] + + if primary_value in self.db['database'][table_name] and not overwrite: + return False + + if len(value) != len(columns_list): + return False + + self.db["database"][table_name][primary_value] = dict(zip(columns_list, value)) + self.logger.info(f"Inserted {value} into {table_name}") + + if commit: self.dump_db() return True diff --git a/requirements.txt b/requirements.txt index bad478a..eb83bf7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -colorama +pandas pytest flake8 \ No newline at end of file diff --git a/setup.py b/setup.py index 62a1696..a13e9d8 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="quickDatabase", - version="0.0.2", + version="0.0.3", author="Deepak Raj", author_email="deepak008@live.com", description="Simple python database", From 2a6d98f3e02ca7dcd0e5207c09ee9bce974b5fb3 Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Thu, 13 Jun 2024 08:37:36 +0530 Subject: [PATCH 13/16] docs requirements added --- docs/requirements.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 docs/requirements.txt diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..cbf1e36 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,2 @@ +sphinx +sphinx-rtd-theme From f9f4981b52ee767954c94cc9345bd7b16e25fee3 Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Sat, 15 Jun 2024 12:33:45 +0530 Subject: [PATCH 14/16] chore: Bump version to 0.0.4 and update documentation and setup.py --- CHANGELOG.md | 6 +++++- README.md | 2 +- docs/conf.py | 2 +- setup.py | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c74f429..5e0a250 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Version 0.0.3 +## Version 0.0.4 - Support for multi insert queries added + +## Version 0.0.3 + - `dum_db` parameter changed to `commit` in insert queries +- Bug fixes ## Version 0.0.2 diff --git a/README.md b/README.md index 2199296..3c53179 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

Quick DB ⚡ 0.0.3

+

Quick DB ⚡ 0.0.4

Light weight database for python, with a simple API and a simple file format. diff --git a/docs/conf.py b/docs/conf.py index f6ddd6e..cee3bd2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,7 +1,7 @@ from datetime import datetime project = 'quickDB' -release = '0.0.3' +release = '0.0.4' templates_path = ['_templates'] source_suffix = ".rst" master_doc = "index" diff --git a/setup.py b/setup.py index a13e9d8..1e66f59 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="quickDatabase", - version="0.0.3", + version="0.0.4", author="Deepak Raj", author_email="deepak008@live.com", description="Simple python database", From f45555ae8165053fba134450a26c4703e9a62aa5 Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Sun, 23 Jun 2024 08:01:39 +0530 Subject: [PATCH 15/16] chore: Bump version to 0.0.5, fix bugs in insert queries, and add debug mode for logging --- CHANGELOG.md | 6 ++++++ README.md | 16 +++++++++------- docs/conf.py | 2 +- quickdb/main.py | 26 +++++++++++++++++--------- setup.py | 2 +- tmp.py | 0 6 files changed, 34 insertions(+), 18 deletions(-) create mode 100644 tmp.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e0a250..2fbbb87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Version 0.0.5 + +- Bug fixes for duplicate values in insert queries +- Bug fixes for already existing tables in insert queries +- debug mode added for logging + ## Version 0.0.4 - Support for multi insert queries added diff --git a/README.md b/README.md index 3c53179..05277e5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

Quick DB ⚡ 0.0.4

+

Quick DB ⚡ 0.0.5

Light weight database for python, with a simple API and a simple file format. @@ -36,10 +36,18 @@ The documentation is available at [Quick DB](https://quickdb.readthedocs.io/en/l You can install the package using pip: +### [Stable version](https://pypi.org/project/quickDatabase/) + ```bash pip install quickdatabase ``` +### [Unstable and latest version](https://test.pypi.org/project/quickDatabase/) + +```bash +pip install -i https://test.pypi.org/simple/ quickDatabase +``` + ## Usage To use QuickDB, you need to import it: @@ -62,9 +70,3 @@ This project is licensed under the MIT License - see the [LICENSE](/LICENSE) fil - -## Author - -- Module : QuickDB -- Author : py-contributors -- Email : pycontributors@gmail.com diff --git a/docs/conf.py b/docs/conf.py index cee3bd2..06461eb 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,7 +1,7 @@ from datetime import datetime project = 'quickDB' -release = '0.0.4' +release = '0.0.5' templates_path = ['_templates'] source_suffix = ".rst" master_doc = "index" diff --git a/quickdb/main.py b/quickdb/main.py index 73937eb..9a6f240 100644 --- a/quickdb/main.py +++ b/quickdb/main.py @@ -33,6 +33,7 @@ def __init__(self, db_path="db.json", db_drop_path="quick_db_output", self.database = self.db['database'] self.db_drop_path = db_drop_path self.db_log_path = db_log_path + self.logger.info("-"*50) def __load_db_from_file(self): """ Load the database from the file """ @@ -100,6 +101,10 @@ def dumb_table(self, table_name, output_format='json'): def create_table(self, table_name, columns_list, primary_key=None): """ Create the schema of the database """ + if table_name in self.schema: + self.logger.error(f"Table {table_name} already exists") + return False + if primary_key not in columns_list: raise ValueError(f"Primary key {primary_key} not in columns list") @@ -134,13 +139,17 @@ def get_table_primary_key(self, table_name): def insert_into(self, table_name, value, overwrite=False, commit=False): """ Set the key-value pair in the database """ - primary_value = value[self.schema[table_name]['primary_key_index']] + primary_value = str(value[self.schema[table_name]['primary_key_index']]) columns_list = self.schema[table_name]['columns_list'] - if primary_value in self.db['database'][table_name] and not overwrite: + database_keys = self.db['database'][table_name].keys() + + if primary_value in database_keys and not overwrite: + self.logger.error(f"Primary key {primary_value} already exists in {table_name}") return False if len(value) != len(columns_list): + self.logger.error(f"Length of value {value} does not match columns list {columns_list}") return False self.db["database"][table_name][primary_value] = dict(zip(columns_list, value)) @@ -153,14 +162,16 @@ def insert_into(self, table_name, value, overwrite=False, commit=False): def insert_into_many(self, table_name, values, overwrite=False, commit=False): """ Set the key-value pair in the database """ for value in values: - primary_value = value[self.schema[table_name]['primary_key_index']] + primary_value = str(value[self.schema[table_name]['primary_key_index']]) columns_list = self.schema[table_name]['columns_list'] - if primary_value in self.db['database'][table_name] and not overwrite: - return False + if primary_value in self.db['database'][table_name].keys() and not overwrite: + self.logger.error(f"Primary key {primary_value} already exists in {table_name}") + continue if len(value) != len(columns_list): - return False + self.logger.error(f"Length of value {value} does not match columns list {columns_list}") + continue self.db["database"][table_name][primary_value] = dict(zip(columns_list, value)) self.logger.info(f"Inserted {value} into {table_name}") @@ -227,6 +238,3 @@ def __repr__(self): def __str__(self): return f"QuickDB(db_path={self.db_path}, db={self.db})" - - def __getitem__(self, key): - return self.db["database"][key] if key in self.db["database"] else None diff --git a/setup.py b/setup.py index 1e66f59..d2fb7eb 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="quickDatabase", - version="0.0.4", + version="0.0.5", author="Deepak Raj", author_email="deepak008@live.com", description="Simple python database", diff --git a/tmp.py b/tmp.py new file mode 100644 index 0000000..e69de29 From 0179f424e156c1a5d88ea2caa6a152b8136793ba Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codePerfectPlus@users.noreply.github.com> Date: Tue, 2 Jul 2024 08:17:23 +0530 Subject: [PATCH 16/16] test cases added --- quickdb/main.py | 8 ++++++-- tests/test_cases.py | 44 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/quickdb/main.py b/quickdb/main.py index 9a6f240..67a3d5c 100644 --- a/quickdb/main.py +++ b/quickdb/main.py @@ -49,7 +49,7 @@ def __init_db(self): if self.overwrite_db and os.path.exists(self.db_path): self.logger.info(f"Overwriting database from {self.db_path}") - self.clear() + self.clear_database() return self.db self.logger.info(f"Creating new database at {self.db_path}") @@ -184,7 +184,11 @@ def get_db(self): """ Get the database along with the schema """ return self.db - def clear(self): + def get_table_data(self, table_name): + """ Get the table data """ + return self.db['database'][table_name] + + def clear_database(self): """ Clear the database """ self.db = {"database": {}, "schema": {}} self.dump_db() diff --git a/tests/test_cases.py b/tests/test_cases.py index 39de25c..b640704 100644 --- a/tests/test_cases.py +++ b/tests/test_cases.py @@ -4,13 +4,53 @@ sys.path.append(".") from quickdb.main import QuickDB - db = QuickDB("test_db.json", overwrite_db=True) class DatabaseTest(unittest.TestCase): - pass + + def test_create_table(self): + table_name = 'employee' + columns = ['serial', 'name', 'age', 'city', 'country', 'email', 'phone', 'salary'] + primary_key = 'serial' + db.create_table(table_name, columns, primary_key) + self.assertEqual(db.get_table_columns(table_name), columns) + + def test_get_table_names(self): + table_name = 'employee' + self.assertEqual(db.get_table_names(), [table_name]) + + def test_get_table(self): + table_name = 'employee' + columns = ['serial', 'name', 'age', 'city', 'country', 'email', 'phone', 'salary'] + primary_key = 'serial' + self.assertEqual(db.get_table(table_name), {"columns_list": columns, + "primary_key": primary_key, + "primary_key_index": 0}) + + def test_get_table_primary_key(self): + table_name = 'employee' + primary_key = 'serial' + self.assertEqual(db.get_table_primary_key(table_name), primary_key) + + def test_insert_into(self): + table_name = 'employee' + db.insert_into(table_name=table_name, + value=[1, 'John Doe', 30, 'New York', 'USA', 'd@mail.com', '1234567890', 50000], commit=True) + self.assertEqual(len(db.get_table_data(table_name)), 1) + + def test_drop_table(self): + table_name = 'student' + columns = ['roll', 'name', 'age', 'city', 'country', 'email', 'phone', 'fees'] + primary_key = 'roll' + db.create_table(table_name, columns, primary_key) + self.assertEqual(db.get_table_names(), ['employee', 'student']) + db.drop_table(table_name) + self.assertEqual(db.get_table_names(), ['employee']) + def test_clear_database(self): + db.clear_database() + self.assertEqual(db.get_db(), {"database": {}, "schema": {}}) if __name__ == '__main__': unittest.main()