Skip to content

Commit

Permalink
Add first(), last() + Support Singleton DB
Browse files Browse the repository at this point in the history
  • Loading branch information
AliRn76 committed Nov 3, 2023
1 parent 03ffbc1 commit 099b458
Show file tree
Hide file tree
Showing 4 changed files with 243 additions and 4 deletions.
24 changes: 21 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ PantherDB is a <b>Simple</b>, <b>FileBase</b> and <b>Document Oriented</b> datab
- Easy to use
- Written in pure Python +3.8 based on standard type hints
- Handle Database Encryption

- Singleton connection per `db_name`

## Usage

Expand Down Expand Up @@ -43,15 +43,33 @@ PantherDB is a <b>Simple</b>, <b>FileBase</b> and <b>Document Oriented</b> datab
```

### Get:
- #### Find first document:
- #### Find one document:
```python
user: PantherDocument = db.collection('User').find_one(first_name='Ali', last_name='Rn')
```
or
```python
user: PantherDocument = db.collection('User').find_one()
```


- #### Find first document (alias of `find_one()`):
```python
user: PantherDocument = db.collection('User').first(first_name='Ali', last_name='Rn')
```
or
```python
user: PantherDocument = db.collection('User').first()
```

- #### Find last document:
```python
user: PantherDocument = db.collection('User').last(first_name='Ali', last_name='Rn')
```
or
```python
user: PantherDocument = db.collection('User').lasst()
```

- #### Find documents:
```python
users: list[PantherDocument] = db.collection('User').find(last_name='Rn')
Expand Down
2 changes: 1 addition & 1 deletion pantherdb/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from pantherdb.pantherdb import * # noqa: F403

__version__ = '1.2.9'
__version__ = '1.3.0'


__all__ = ('__version__', 'PantherDB', 'PantherCollection', 'PantherDocument', 'PantherDBException')
31 changes: 31 additions & 0 deletions pantherdb/pantherdb.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

from pathlib import Path
from typing import ClassVar

import orjson as json
from cryptography.fernet import Fernet, InvalidToken
Expand All @@ -11,12 +12,29 @@ class PantherDBException(Exception):


class PantherDB:
_instances: ClassVar[dict] = {}
db_name: str = 'database.pdb'
__secret_key: bytes | None
__fernet: Fernet | None
__return_dict: bool
__content: dict

def __new__(cls, *args, **kwargs):
if cls.__name__ != 'PantherDB':
return super().__new__(cls)

if args:
db_name = args[0]
elif 'db_name' in kwargs:
db_name = kwargs['db_name']
else:
db_name = cls.db_name

db_name = db_name.removesuffix('.pdb')
if db_name not in cls._instances:
cls._instances[db_name] = super().__new__(cls)
return cls._instances[db_name]

def __init__(
self,
db_name: str | None = None,
Expand Down Expand Up @@ -154,6 +172,11 @@ def _get_collection(self) -> list[dict]:

def find_one(self, **kwargs) -> PantherDocument | dict | None:
documents = self._get_collection()

# Empty Collection
if not documents:
return None

if not kwargs:
if self.return_dict:
return documents[0]
Expand All @@ -180,6 +203,14 @@ def find(self, **kwargs) -> list[PantherDocument | dict]:
result.append(self.__create_result(r))
return result

def first(self, **kwargs) -> PantherDocument | dict | None:
return self.find_one(**kwargs)

def last(self, **kwargs) -> PantherDocument | dict | None:
if result := self.find(**kwargs):
return result[-1]
return None

def all(self) -> list[PantherDocument | dict]:
if self.return_dict:
return self._get_collection()
Expand Down
190 changes: 190 additions & 0 deletions tests/test_normal.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,22 @@ def create_junk_document(cls, collection) -> int:
collection.insert_one(first_name=f'{f.first_name()}{i}', last_name=f'{f.last_name()}{i}')
return _count

# Singleton
def test_pantherdb_singleton(self):
test_1 = PantherDB(db_name='test1')
test_2 = PantherDB('test1')
self.assertEqual(test_1, test_2)

default_1 = PantherDB()
default_2 = PantherDB()
self.assertEqual(default_1, default_2)

self.assertNotEqual(test_1, default_1)
self.assertNotEqual(test_2, default_2)

Path(test_1.db_name).unlink()
Path(default_1.db_name).unlink()

# Create DB
def test_creation_of_db(self):
self.assertTrue(Path(self.db_name).exists())
Expand Down Expand Up @@ -131,6 +147,180 @@ def test_find_one_none(self):
obj = collection.find_one(first_name=first_name, last_name=last_name)
self.assertIsNone(obj)

def test_find_one_with_kwargs_from_empty_collection(self):
collection = self.db.collection(f.word())

# Find
obj = collection.find_one(first_name=f.first_name(), last_name=f.last_name())
self.assertIsNone(obj)

def test_find_one_without_kwargs_from_empty_collection(self):
collection = self.db.collection(f.word())

# Find
obj = collection.find_one()
self.assertIsNone(obj)

# First
def test_first_when_its_first(self):
collection = self.db.collection(f.word())
first_name = f.first_name()
last_name = f.last_name()

# Insert with specific names
collection.insert_one(first_name=first_name, last_name=last_name)

# Add others
self.create_junk_document(collection)

# Find
obj = collection.first(first_name=first_name, last_name=last_name)
self.assertTrue(isinstance(obj, PantherDocument))
self.assertEqual(obj.first_name, first_name)
self.assertEqual(obj.last_name, last_name)

def test_first_of_many_finds(self):
collection = self.db.collection(f.word())
first_name = f.first_name()
last_name = f.last_name()

# Insert with specific names
expected = collection.insert_one(first_name=first_name, last_name=last_name)
collection.insert_one(first_name=first_name, last_name=last_name)
collection.insert_one(first_name=first_name, last_name=last_name)

# Add others
self.create_junk_document(collection)

# Find
obj = collection.first(first_name=first_name, last_name=last_name)
self.assertTrue(isinstance(obj, PantherDocument))
self.assertEqual(obj.id, expected.id)

def test_first_when_its_last(self):
collection = self.db.collection(f.word())
first_name = f.first_name()
last_name = f.last_name()

# Add others
self.create_junk_document(collection)

# Insert with specific names
expected = collection.insert_one(first_name=first_name, last_name=last_name)

# Find
obj = collection.first(first_name=first_name, last_name=last_name)
self.assertTrue(isinstance(obj, PantherDocument))
self.assertEqual(obj.first_name, first_name)
self.assertEqual(obj.last_name, last_name)
self.assertEqual(obj.id, expected.id)

def test_first_none(self):
collection = self.db.collection(f.word())
first_name = f.first_name()
last_name = f.last_name()

# Add others
self.create_junk_document(collection)

# Find
obj = collection.first(first_name=first_name, last_name=last_name)
self.assertIsNone(obj)

def test_first_with_kwargs_from_empty_collection(self):
collection = self.db.collection(f.word())

# Find
obj = collection.first(first_name=f.first_name(), last_name=f.last_name())
self.assertIsNone(obj)

def test_first_without_kwargs_from_empty_collection(self):
collection = self.db.collection(f.word())

# Find
obj = collection.first()
self.assertIsNone(obj)

# Last
def test_last_when_its_first(self):
collection = self.db.collection(f.word())
first_name = f.first_name()
last_name = f.last_name()

# Insert with specific names
collection.insert_one(first_name=first_name, last_name=last_name)

# Add others
self.create_junk_document(collection)

# Find
obj = collection.first(first_name=first_name, last_name=last_name)
self.assertTrue(isinstance(obj, PantherDocument))
self.assertEqual(obj.first_name, first_name)
self.assertEqual(obj.last_name, last_name)

def test_last_of_many_finds(self):
collection = self.db.collection(f.word())
first_name = f.first_name()
last_name = f.last_name()

# Insert with specific names
collection.insert_one(first_name=first_name, last_name=last_name)
collection.insert_one(first_name=first_name, last_name=last_name)
expected = collection.insert_one(first_name=first_name, last_name=last_name)

# Add others
self.create_junk_document(collection)

# Find
obj = collection.last(first_name=first_name, last_name=last_name)
self.assertTrue(isinstance(obj, PantherDocument))
self.assertEqual(obj.id, expected.id)

def test_last_when_its_last(self):
collection = self.db.collection(f.word())
first_name = f.first_name()
last_name = f.last_name()

# Add others
self.create_junk_document(collection)

# Insert with specific names
expected = collection.insert_one(first_name=first_name, last_name=last_name)

# Find
obj = collection.last(first_name=first_name, last_name=last_name)
self.assertTrue(isinstance(obj, PantherDocument))
self.assertEqual(obj.first_name, first_name)
self.assertEqual(obj.last_name, last_name)
self.assertEqual(obj.id, expected.id)

def test_last_none(self):
collection = self.db.collection(f.word())
first_name = f.first_name()
last_name = f.last_name()

# Add others
self.create_junk_document(collection)

# Find
obj = collection.last(first_name=first_name, last_name=last_name)
self.assertIsNone(obj)

def test_last_with_kwargs_from_empty_collection(self):
collection = self.db.collection(f.word())

# Find
obj = collection.last(first_name=f.first_name(), last_name=f.last_name())
self.assertIsNone(obj)

def test_last_without_kwargs_from_empty_collection(self):
collection = self.db.collection(f.word())

# Find
obj = collection.last()
self.assertIsNone(obj)

# Find
def test_find_response_type(self):
collection = self.db.collection(f.word())
Expand Down

0 comments on commit 099b458

Please sign in to comment.