Skip to content

Commit 1fab596

Browse files
author
Arjan
committed
Added monadic error handling example
1 parent 3f52af9 commit 1fab596

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed
Binary file not shown.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import sqlite3
2+
from returns.result import Result, safe
3+
from returns.pipeline import flow
4+
from returns.pointfree import bind
5+
6+
class SQLite():
7+
def __init__(self, file='application.db'):
8+
self.file=file
9+
def __enter__(self):
10+
self.conn = sqlite3.connect(self.file)
11+
return self.conn.cursor()
12+
def __exit__(self, type, value, traceback):
13+
self.conn.close()
14+
15+
class NotFoundError(Exception):
16+
pass
17+
18+
class NotAuthorizedError(Exception):
19+
pass
20+
21+
def fetch_blog(blog_id) -> Result['Blog', Exception]:
22+
return flow(
23+
blog_id,
24+
fetch_blog_from_db,
25+
bind(blog_to_dict),
26+
bind(verify_access)
27+
)
28+
29+
@safe
30+
def fetch_blog_from_db(blog_id):
31+
"""Fetches blog from SQLite3 database."""
32+
with SQLite('application.db') as cur:
33+
cur.execute(f"SELECT * FROM blogs where id=?", [blog_id])
34+
result = cur.fetchone()
35+
if result is None:
36+
raise NotFoundError(f'Unable to find blog with id {blog_id}.')
37+
return result
38+
39+
@safe
40+
def blog_to_dict(item) -> 'Blog':
41+
"""Convert SQLite result to dictionary."""
42+
return {
43+
'id': item[0],
44+
'published': item[1],
45+
'title': item[2],
46+
'content': item[3],
47+
'public': bool(item[4])
48+
}
49+
50+
@safe
51+
def verify_access(blog) -> 'Blog':
52+
"""Check that blog is accessible."""
53+
blog_id = blog['id']
54+
blog_public = blog['public']
55+
if not blog_public:
56+
raise NotAuthorizedError(f'You are not allowed to access blog with id {blog_id}.')
57+
return blog
58+
59+
res = fetch_blog("first-blog")
60+
print(res)

0 commit comments

Comments
 (0)