Skip to content

Commit 99e69a8

Browse files
authored
Add basic update event (#100)
* Add basic update event
1 parent b119281 commit 99e69a8

File tree

4 files changed

+103
-13
lines changed

4 files changed

+103
-13
lines changed

app/routers/event.py

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1+
from datetime import datetime
12
from operator import attrgetter
2-
from typing import List
3+
from typing import Dict, List, Optional, Any
34

4-
from fastapi import APIRouter, Request
5-
6-
from app.database.models import Event
7-
from app.database.models import UserEvent
5+
from app.database.models import Event, UserEvent
86
from app.dependencies import templates
97
from app.internal.utils import create_model
8+
from fastapi import APIRouter, Request
9+
from sqlalchemy.exc import SQLAlchemyError
10+
from sqlalchemy.orm import Session
1011

1112
router = APIRouter(
1213
prefix="/event",
@@ -27,6 +28,57 @@ async def eventview(request: Request, id: int):
2728
{"request": request, "event_id": id})
2829

2930

31+
def by_id(db: Session, event_id: int) -> Event:
32+
"""Select event by id"""
33+
34+
return db.query(Event).filter(Event.id == event_id).first()
35+
36+
37+
def is_date_before(start_date: datetime, end_date: datetime) -> bool:
38+
"""Check if the start date is earlier than the end date"""
39+
40+
return start_date < end_date
41+
42+
43+
def is_it_possible_to_change_dates(
44+
db: Session, old_event: Event, event: Dict[str, Any]) -> bool:
45+
return is_date_before(
46+
event.get('start', old_event.start),
47+
event.get('end', old_event.end))
48+
49+
50+
def get_items_that_can_be_updated(event: Dict[str, Any]) -> Dict[str, Any]:
51+
"""Extract only that keys to update"""
52+
53+
return {i: event[i] for i in (
54+
'title', 'start', 'end', 'content', 'location') if i in event}
55+
56+
57+
def update_event(event_id: int, event: Dict, db: Session
58+
) -> Optional[Event]:
59+
60+
# TODO Check if the user is the owner of the event.
61+
62+
event_to_update = get_items_that_can_be_updated(event)
63+
if not event_to_update:
64+
return None
65+
try:
66+
old_event = by_id(db=db, event_id=event_id)
67+
if old_event is None or not is_it_possible_to_change_dates(
68+
db, old_event, event_to_update):
69+
return None
70+
71+
# Update database
72+
db.query(Event).filter(Event.id == event_id).update(
73+
event_to_update, synchronize_session=False)
74+
db.commit()
75+
76+
# TODO: Send emails to recipients.
77+
except (AttributeError, SQLAlchemyError, TypeError):
78+
return None
79+
return by_id(db=db, event_id=event_id)
80+
81+
3082
def create_event(db, title, start, end, owner_id, content=None, location=None):
3183
"""Creates an event and an association."""
3284

app/routers/profile.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ async def profile(
4343
session.commit()
4444
user = session.query(User).filter_by(id=1).first()
4545

46-
session.close()
47-
4846
return templates.TemplateResponse("profile.html", {
4947
"request": request,
5048
"user": user,
@@ -64,8 +62,6 @@ async def update_user_fullname(
6462
user.full_name = new_fullname
6563
session.commit()
6664

67-
session.close()
68-
6965
url = router.url_path_for("profile")
7066
response = RedirectResponse(url=url, status_code=HTTP_302_FOUND)
7167
return response
@@ -83,8 +79,6 @@ async def update_user_email(
8379
user.email = new_email
8480
session.commit()
8581

86-
session.close()
87-
8882
url = router.url_path_for("profile")
8983
return RedirectResponse(url=url, status_code=HTTP_302_FOUND)
9084

@@ -101,8 +95,6 @@ async def update_profile(
10195
user.description = new_description
10296
session.commit()
10397

104-
session.close()
105-
10698
url = router.url_path_for("profile")
10799
return RedirectResponse(url=url, status_code=HTTP_302_FOUND)
108100

requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ iniconfig==1.1.1
3838
Jinja2==2.11.2
3939
joblib==1.0.0
4040
lazy-object-proxy==1.5.2
41+
mypy==0.790
42+
mypy-extensions==0.4.3
4143
MarkupSafe==1.1.1
4244
nltk==3.5
4345
packaging==20.8
@@ -68,11 +70,13 @@ smtpdfix==0.2.6
6870
sniffio==1.2.0
6971
sortedcontainers==2.3.0
7072
soupsieve==2.1
73+
sortedcontainers==2.3.0
7174
SQLAlchemy==1.3.22
7275
starlette==0.13.6
7376
text-unidecode==1.3
7477
toml==0.10.2
7578
tqdm==4.56.0
79+
typed-ast==1.4.2
7680
typing-extensions==3.7.4.3
7781
urllib3==1.26.2
7882
uvicorn==0.13.3

tests/test_event.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
1+
from datetime import datetime
2+
3+
import pytest
4+
from app.database.models import Event
5+
from app.routers.event import update_event
16
from starlette.status import HTTP_404_NOT_FOUND
27

8+
INVALID_UPDATE_OPTIONS = [
9+
{}, {"test": "test"}, {"start": "20.01.2020"},
10+
{"start": datetime(2020, 2, 2), "end": datetime(2020, 1, 1)},
11+
{"start": datetime(2030, 2, 2)}, {"end": datetime(1990, 1, 1)},
12+
]
13+
314

415
class TestEvent:
516

@@ -17,5 +28,36 @@ def test_eventview_without_id(self, client):
1728
response = client.get("/event/view")
1829
assert response.status_code == HTTP_404_NOT_FOUND
1930

31+
@staticmethod
32+
@pytest.mark.parametrize("data", INVALID_UPDATE_OPTIONS)
33+
def test_invalid_update(event, data, session):
34+
assert update_event(event_id=event.id,
35+
event=data, db=session) is None
36+
37+
@staticmethod
38+
def test_successful_update(event, session):
39+
data = {
40+
"title": "successful",
41+
"start": datetime(2021, 1, 20),
42+
"end": datetime(2021, 1, 21),
43+
}
44+
assert isinstance(update_event(1, data, session), Event)
45+
assert "successful" in update_event(
46+
event_id=event.id, event=data, db=session).title
47+
48+
@staticmethod
49+
def test_update_db_close(event):
50+
data = {"title": "Problem connecting to db", }
51+
assert update_event(event_id=event.id,
52+
event=data, db=None) is None
53+
54+
@staticmethod
55+
def test_update_event_does_not_exist(event, session):
56+
data = {
57+
"content": "An update test for an event does not exist"
58+
}
59+
assert update_event(
60+
event_id=500, event=data, db=session) is None
61+
2062
def test_repr(self, event):
2163
assert event.__repr__() == f'<Event {event.id}>'

0 commit comments

Comments
 (0)