Skip to content

Commit

Permalink
Merge pull request #4 from MissterHao/feature/delete
Browse files Browse the repository at this point in the history
New feature: delete session method
  • Loading branch information
MissterHao authored Feb 3, 2023
2 parents 1b384af + 5a71d09 commit 97a64a0
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 25 deletions.
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ jobs:
python -m pip install --upgrade pip
pip install setuptools wheel twine
python setup.py sdist bdist_wheel
cp dist/django-dysession-${{ env.STRIP_RELEASE_VERSION }}.tar.gz dist/django-dysession.tar.gz
- name: Archive wheel artifacts file
uses: actions/upload-artifact@v3
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<div align="center">
<h1>django-dysession</h1>
<p>django-dysession is a django extension by using AWS DynamoDB as a session backend</p>
<img src="https://socialify.git.ci/MissterHao/django-dysession/image?description=1&font=Source%20Code%20Pro&language=1&name=1&owner=1&pattern=Plus&stargazers=1&theme=Light" alt="django-dysession" width="640" height="320" />
<img src="asset/banner.png" alt="django-dysession" width="640" height="320" />
<!-- <img src="https://socialify.git.ci/MissterHao/django-dysession/image?description=1&font=Source%20Code%20Pro&language=1&name=1&owner=1&pattern=Plus&stargazers=1&theme=Light" alt="django-dysession" width="640" height="320" /> -->

<p align="center" >
<!-- First line -->
Expand Down Expand Up @@ -82,9 +83,12 @@ def mainpage(request):
request.session["planet_have_been_to"] = ["Earth", "Jupiter", "Saturn"]

return HttpResponse("Ayyy")

```

Enjoy!

![](asset/dynamodb-real-demo-image.png)


## Django Commands

Expand Down
Binary file added asset/banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added asset/dynamodb-real-demo-image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions dysession/aws/dynamodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,32 @@ def insert_session_item(
return response


def delete_session_item(
data: SessionDataModel,
table_name: Optional[str] = None,
) -> bool:
"""Delete a session key"""

assert type(data.session_key) is str, "session_key should be string type"

if table_name is None:
table_name = get_config()["DYNAMODB_TABLENAME"]

resource = boto3.resource("dynamodb", region_name=get_config()["DYNAMODB_REGION"])
table = resource.Table(table_name)
pk = get_config()["PARTITION_KEY_NAME"]

insert_item = {pk: data.session_key}
for key in data:
insert_item[key] = data[key]

response = table.delete_item(
Key={pk: data.session_key},
)

return response


class DynamoDB:
def __init__(self, client=None) -> None:
self.client = client
Expand Down Expand Up @@ -206,3 +232,9 @@ def exists(self, session_key: str) -> bool:
)

return key_exists(session_key=session_key)

def delete(self, data: SessionDataModel, table_name: Optional[str] = None) -> bool:
try:
delete_session_item(data=data, table_name=table_name)
except AssertionError:
raise
9 changes: 7 additions & 2 deletions dysession/backends/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from dysession.aws.dynamodb import DynamoDB
from dysession.backends.error import (
DeleteSessionError,
SessionExpired,
SessionKeyDoesNotExist,
SessionKeyDuplicated,
Expand Down Expand Up @@ -120,9 +121,13 @@ def delete(self, session_key=None):
Delete the session data under this key. If the key is None, use the
current session key value.
"""
if session_key is None:
session_key = self._session_key


try:
self.db.delete(session_key=self._session_key)
except:
self.db.delete(self._get_session())
except DeleteSessionError:
pass

def load(self) -> SessionDataModel:
Expand Down
4 changes: 4 additions & 0 deletions dysession/backends/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ class SessionKeyDoesNotExist(Exception):

class SessionKeyDuplicated(Exception):
...


class DeleteSessionError(Exception):
...
19 changes: 13 additions & 6 deletions dysession/backends/model.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import json
from typing import Any, Optional

from dysession.settings import get_config


class SessionDataModel:

Expand All @@ -11,8 +13,8 @@ def __init__(self, session_key: Optional[str] = None) -> None:
if type(session_key) is not str and session_key is not None:
raise TypeError("session_key should be type str or None")

self.session_key = session_key
self.__variables_names = set(["session_key"])
self.__variables_names = set([])
self[get_config()["PARTITION_KEY_NAME"]] = session_key

def __getitem__(self, key) -> Any:
# Set SESSION_EXPIRE_AT_BROWSER_CLOSE to False
Expand All @@ -27,10 +29,15 @@ def __getitem__(self, key) -> Any:
raise KeyError
raise

def __setitem__(self, key, value):
# if key == "session_key":
# raise ValueError()
def __get_session_key(self):
return self[get_config()["PARTITION_KEY_NAME"]]

def __set_session_key(self, value: Any):
self[get_config()["PARTITION_KEY_NAME"]] = value

session_key = property(__get_session_key, __set_session_key)

def __setitem__(self, key, value):
setattr(self, key, value)
self.__variables_names.add(key)

Expand All @@ -42,7 +49,7 @@ def __iter__(self):
return iter(self.__variables_names)

def __is_empty(self):
return "session_key" in self.__variables_names and len(self.__variables_names) == 1
return len(self.__variables_names) == 0

is_empty = property(__is_empty)

Expand Down
2 changes: 1 addition & 1 deletion dysession/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.1
1.0.2
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ description = "django-dysession is a django extension which integrated AWS Dynam
long_description = file: README.md
long_description_content_type = text/markdown
keywords = "django,session,aws,dynamodb"
url = https://github.com/MissterHao/django-dysession/releases/download/v1.0.1/django-dysession-1.0.1.tar.gz
download_url = https://github.com/MissterHao/django-dysession/releases/download/v1.0.1/django-dysession-1.0.1.tar.gz
url = https://github.com/MissterHao/django-dysession/releases/latest/download/django-dysession.tar.gz
download_url = https://github.com/MissterHao/django-dysession/releases/latest/download/django-dysession.tar.gz
author = "Hao-Wei, Li"
author_email = "[email protected]"
maintainer = "MissterHao"
Expand Down
54 changes: 48 additions & 6 deletions tests/test_aws_dynamodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from dysession.aws.dynamodb import (
check_dynamodb_table_exists,
create_dynamodb_table,
delete_session_item,
destory_dynamodb_table,
get_item,
insert_session_item,
Expand Down Expand Up @@ -362,9 +363,7 @@ def test_get_item_using_not_exist_key(self):
)

with self.assertRaises(DynamodbItemNotFound):
resp = get_item(
session_key="not_exist_key", table_name=options["table"]
)
resp = get_item(session_key="not_exist_key", table_name=options["table"])

# Insert Item
@parameterized.expand(
Expand Down Expand Up @@ -407,9 +406,7 @@ def test_insert_item_with_tablename(self, session_key: str):
resp = insert_session_item(data=model)
self.assertEqual(resp["ResponseMetadata"]["HTTPStatusCode"], 200)

resp = get_item(
session_key=session_key, table_name=options["table"]
)
resp = get_item(session_key=session_key, table_name=options["table"])
self.assertIsInstance(resp, SessionDataModel)

@parameterized.expand(
Expand Down Expand Up @@ -454,3 +451,48 @@ def test_insert_item_without_tablename(self, session_key: str):

resp = get_item(session_key=session_key)
self.assertIsInstance(resp, SessionDataModel)

@parameterized.expand(
[
["aaaaaaaaa"],
["bbbbbbbbb"],
["ccccccccc"],
]
)
@mock_dynamodb
def test_delete_item_without_tablename(self, session_key: str):

options = {
"pk": get_config()["PARTITION_KEY_NAME"],
"sk": get_config()["SORT_KEY_NAME"],
"table": "sessions",
"region": "ap-northeast-1",
}

client = boto3.client("dynamodb", region_name=options["region"])
try:
check_dynamodb_table_exists(table_name=options["table"], client=client)
except DynamodbTableNotFound:
create_dynamodb_table(
options={
"pk": options["pk"],
"sk": options["sk"],
"table": options["table"],
},
client=client,
)

model = SessionDataModel(session_key)
model["a"] = 1
model["b"] = 2
model["c"] = 3
model["d"] = 4
model["e"] = "qwerty"

resp = insert_session_item(data=model)
self.assertEqual(resp["ResponseMetadata"]["HTTPStatusCode"], 200)

resp = delete_session_item(data=model)

with self.assertRaises(DynamodbItemNotFound):
resp = get_item(session_key=session_key)
31 changes: 31 additions & 0 deletions tests/test_backend_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,34 @@ def test_exist_check_input_type_error_via_dynamodb_controller(

with self.assertRaises(TypeError):
db.exists(error_input)

@mock_dynamodb
def test_delete_item_via_dynamodb_controller(self):

session_key = "test_set_duplicated_datamodel_via_dynamodb_controller"
self.create_dynamodb_table()

model = SessionDataModel(session_key)
model["a"] = 1
model[get_config()["TTL_ATTRIBUTE_NAME"]] = int(datetime.now().timestamp()) + 50

db = DynamoDB(self.client)
db.set(model, get_config()["DYNAMODB_TABLENAME"])
query_model = db.get(session_key=session_key)
self.assertEqual(model.a, query_model.a)

db.delete(model)

@mock_dynamodb
def test_delete_item_via_dynamodb_controller_raise_error(self):

session_key = None
self.create_dynamodb_table()

model = SessionDataModel(session_key)
model["a"] = 1
model[get_config()["TTL_ATTRIBUTE_NAME"]] = int(datetime.now().timestamp()) + 50

db = DynamoDB(self.client)
with self.assertRaises(AssertionError):
db.delete(model)
18 changes: 12 additions & 6 deletions tests/test_backend_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,13 @@ def test_get_function_default_value(self):

def test_is_empty(self):
model = SessionDataModel()
self.assertTrue(model.is_empty)
self.assertFalse(model.is_empty)

model["good_key"] = 0
self.assertFalse(model.is_empty)

del model["good_key"]
self.assertTrue(model.is_empty)
self.assertFalse(model.is_empty)

def test_iter(self):
model = SessionDataModel()
Expand All @@ -105,7 +105,7 @@ def test_iter(self):
model["c"] = 1
model["d"] = 1

self.assertEqual(set(model), set(["a", "b", "c", "d", "session_key"]))
self.assertEqual(set(model), set(["a", "b", "c", "d", "PK"]))

def test_items(self):
model = SessionDataModel("session_key")
Expand All @@ -123,7 +123,7 @@ def test_items(self):
values.append(v)


self.assertEqual(set(keys), set(["a", "b", "c", "d", "session_key"]))
self.assertEqual(set(keys), set(["a", "b", "c", "d", "PK"]))
self.assertEqual(set(values), set([1, 2, 3, 4, "session_key"]))

def test_str_magic_method(self):
Expand All @@ -137,7 +137,7 @@ def test_str_magic_method(self):

data = json.loads(str(model))

for k in ["session_key", "a", "b", "c", "d"]:
for k in ["PK", "a", "b", "c", "d"]:
self.assertIn(k, data.keys())

def test_get__session_expiry(self):
Expand All @@ -152,4 +152,10 @@ def test_not_found_allow_list(self):
model[k]

with self.assertRaises(KeyError):
self.assertIsNone(model.get(k))
self.assertIsNone(model.get(k))


def test_get_and_set_session_key(self):
model = SessionDataModel()
model.session_key = "key"
self.assertEqual(model.session_key, "key")

0 comments on commit 97a64a0

Please sign in to comment.