andreped commited on
Commit
9d864fa
·
unverified ·
2 Parent(s): 80ce652 1108709

Merge pull request #3 from andreped/streamlit-demo

Browse files

Implemented simple streamlit demo to showcase client

app.py ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+
3
+ from postly.clients.postly_client import PostlyClient
4
+
5
+ # Initialize the PostlyClient in Streamlit's session state
6
+ if "client" not in st.session_state:
7
+ st.session_state.client = PostlyClient()
8
+
9
+ client = st.session_state.client
10
+
11
+
12
+ def add_user():
13
+ st.title("Add User")
14
+ user_name = st.text_input("Enter user name")
15
+ if st.button("Add User"):
16
+ client.add_user(user_name)
17
+ st.success(f"User '{user_name}' added successfully.")
18
+
19
+
20
+ def add_post():
21
+ st.title("Add Post")
22
+ users = client.get_users()
23
+ user_name = st.selectbox("Select user name", users)
24
+ post_text = st.text_area("Enter post text")
25
+ if st.button("Add Post"):
26
+ try:
27
+ client.add_post(user_name, post_text)
28
+ st.success("Post added successfully.")
29
+ except Exception as e:
30
+ st.error(f"Error: {e}")
31
+
32
+
33
+ def delete_user():
34
+ st.title("Delete User")
35
+ users = client.get_users()
36
+ user_name = st.selectbox("Select user name", users)
37
+ if st.button("Delete User"):
38
+ try:
39
+ client.delete_user(user_name)
40
+ st.success(f"User '{user_name}' deleted successfully.")
41
+ except KeyError as e:
42
+ st.error(f"Error: {e}")
43
+
44
+
45
+ def get_posts_for_user():
46
+ st.title("Get Posts for User")
47
+ users = client.get_users()
48
+ user_name = st.selectbox("Select user name", users)
49
+ if st.button("Get Posts"):
50
+ try:
51
+ posts = client.get_posts_for_user(user_name)
52
+ st.write(f"Posts for user '{user_name}':")
53
+ for post in posts:
54
+ st.write(post)
55
+ except KeyError as e:
56
+ st.error(f"Error: {e}")
57
+
58
+
59
+ def get_posts_for_topic():
60
+ st.title("Get Posts for Topic")
61
+ topics = client.get_topics()
62
+ topic = st.selectbox("Enter topic", topics)
63
+ if st.button("Get Posts"):
64
+ posts = client.get_posts_for_topic(topic)
65
+ st.write(f"Posts for topic '{topic}':")
66
+ for post in posts:
67
+ st.write(post)
68
+
69
+
70
+ def get_trending_topics():
71
+ st.title("Get Trending Topics")
72
+ current_timestamp = client.get_current_timestamp()
73
+ from_timestamp = st.number_input("Enter from timestamp", min_value=0, step=1)
74
+ to_timestamp = st.number_input(
75
+ "Enter to timestamp", min_value=0, max_value=current_timestamp, step=1, value=current_timestamp
76
+ )
77
+ if st.button("Get Trending Topics"):
78
+ try:
79
+ topics = client.get_trending_topics(int(from_timestamp), int(to_timestamp))
80
+ st.write("Trending topics:")
81
+ for topic in topics:
82
+ st.write(topic)
83
+ except ValueError as e:
84
+ st.error(f"Error: {e}")
85
+ st.rerun()
86
+
87
+
88
+ def get_all_posts():
89
+ st.title("All Posts")
90
+ posts = client.get_posts()
91
+ all_posts = []
92
+ for user_name, user_posts in posts.items():
93
+ for post in user_posts:
94
+ all_posts.append((user_name, post))
95
+ sorted_posts = sorted(all_posts, key=lambda x: x[1].timestamp)
96
+ for user_name, post in sorted_posts:
97
+ st.markdown(f"**{user_name}**")
98
+ st.markdown(f"{post.content}")
99
+ st.markdown("---")
100
+
101
+
102
+ def main():
103
+ st.sidebar.title("Postly\nSimple social media platform")
104
+ page = st.sidebar.selectbox(
105
+ "Choose an action",
106
+ [
107
+ "Add User",
108
+ "Add Post",
109
+ "Delete User",
110
+ "Get Posts for User",
111
+ "Get Posts for Topic",
112
+ "Get Trending Topics",
113
+ "View All Posts",
114
+ ],
115
+ index=6,
116
+ )
117
+
118
+ if page == "Add User":
119
+ add_user()
120
+ elif page == "Add Post":
121
+ add_post()
122
+ elif page == "Delete User":
123
+ delete_user()
124
+ elif page == "Get Posts for User":
125
+ get_posts_for_user()
126
+ elif page == "Get Posts for Topic":
127
+ get_posts_for_topic()
128
+ elif page == "Get Trending Topics":
129
+ get_trending_topics()
130
+ elif page == "View All Posts":
131
+ get_all_posts()
132
+
133
+
134
+ if __name__ == "__main__":
135
+ main()
postly/clients/postly_client.py CHANGED
@@ -41,14 +41,13 @@ class PostlyClient:
41
  """
42
  self.userPosts[user_name] = []
43
 
44
- def add_post(self, user_name: str, post_text: str, timestamp: int) -> None:
45
  """
46
  Add new post to the user's post history.
47
 
48
  Args:
49
  user_name: The name of the user to add the post to.
50
  post_text: The text of the post.
51
- timestamp: The timestamp of the post.
52
  Returns:
53
  None
54
  """
@@ -61,9 +60,6 @@ class PostlyClient:
61
  if not post_text.strip():
62
  raise ValueError("Post cannot be empty.")
63
 
64
- if not isinstance(timestamp, int) or timestamp < 0:
65
- raise ValueError("Timestamp must be a non-negative integer.")
66
-
67
  self.timestamp_iter += 1
68
  curr_topics = self.get_topics_from_post(post_text)
69
 
@@ -83,6 +79,47 @@ class PostlyClient:
83
 
84
  self.userPosts.pop(user_name, None)
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  def get_posts_for_user(self, user_name: str) -> List[str]:
87
  """
88
  Get all posts for user, sorted by timestamp in descending order.
 
41
  """
42
  self.userPosts[user_name] = []
43
 
44
+ def add_post(self, user_name: str, post_text: str) -> None:
45
  """
46
  Add new post to the user's post history.
47
 
48
  Args:
49
  user_name: The name of the user to add the post to.
50
  post_text: The text of the post.
 
51
  Returns:
52
  None
53
  """
 
60
  if not post_text.strip():
61
  raise ValueError("Post cannot be empty.")
62
 
 
 
 
63
  self.timestamp_iter += 1
64
  curr_topics = self.get_topics_from_post(post_text)
65
 
 
79
 
80
  self.userPosts.pop(user_name, None)
81
 
82
+ def get_users(self):
83
+ """
84
+ Get all users.
85
+
86
+ Returns:
87
+ A list of users.
88
+ """
89
+ return list(self.userPosts.keys())
90
+
91
+ def get_posts(self):
92
+ """
93
+ Get all posts for all users.
94
+
95
+ Returns:
96
+ A dictionary of posts.
97
+ """
98
+ return self.userPosts
99
+
100
+ def get_topics(self) -> List[str]:
101
+ """
102
+ Get all topics.
103
+
104
+ Returns:
105
+ A list of topics.
106
+ """
107
+ topics = set()
108
+ for user in self.userPosts:
109
+ for post_data in self.userPosts[user]:
110
+ topics.update(post_data.topics)
111
+
112
+ return list(topics)
113
+
114
+ def get_current_timestamp(self) -> int:
115
+ """
116
+ Get the current timestamp.
117
+
118
+ Returns:
119
+ The current timestamp.
120
+ """
121
+ return self.timestamp_iter
122
+
123
  def get_posts_for_user(self, user_name: str) -> List[str]:
124
  """
125
  Get all posts for user, sorted by timestamp in descending order.
requirements.txt CHANGED
@@ -3,3 +3,4 @@ isort
3
  black
4
  pydantic
5
  pytest
 
 
3
  black
4
  pydantic
5
  pytest
6
+ streamlit
shell/format.sh CHANGED
@@ -1,4 +1,4 @@
1
  #!/bin/bash
2
- isort --sl postly/
3
- black --line-length 120 postly/
4
- flake8 --max-line-length 120 postly/
 
1
  #!/bin/bash
2
+ isort --sl postly/ tests/ app.py
3
+ black --line-length 120 postly/ tests/ app.py
4
+ flake8 --max-line-length 120 postly/ tests/ app.py
shell/lint.sh CHANGED
@@ -1,19 +1,19 @@
1
  #!/bin/bash
2
- isort --check --sl -c postly/
3
  if ! [ $? -eq 0 ]
4
  then
5
  echo "Please run \"sh shell/format.sh\" to format the code."
6
  exit 1
7
  fi
8
  echo "no issues with isort"
9
- flake8 --max-line-length 120 postly/
10
  if ! [ $? -eq 0 ]
11
  then
12
  echo "Please fix the code style issue."
13
  exit 1
14
  fi
15
  echo "no issues with flake8"
16
- black --check --line-length 120 postly/
17
  if ! [ $? -eq 0 ]
18
  then
19
  echo "Please run \"sh shell/format.sh\" to format the code."
 
1
  #!/bin/bash
2
+ isort --check --sl -c postly/ tests/ app.py
3
  if ! [ $? -eq 0 ]
4
  then
5
  echo "Please run \"sh shell/format.sh\" to format the code."
6
  exit 1
7
  fi
8
  echo "no issues with isort"
9
+ flake8 --max-line-length 120 postly/ tests/ app.py
10
  if ! [ $? -eq 0 ]
11
  then
12
  echo "Please fix the code style issue."
13
  exit 1
14
  fi
15
  echo "no issues with flake8"
16
+ black --check --line-length 120 postly/ tests/ app.py
17
  if ! [ $? -eq 0 ]
18
  then
19
  echo "Please run \"sh shell/format.sh\" to format the code."
tests/test_plotly.py CHANGED
@@ -6,21 +6,17 @@ class TestPlotlyClient:
6
  self.postly_instance = PostlyClient()
7
 
8
  # define reference data for testing
9
- self.gt_posts = [
10
- "just #chilling today",
11
- "eating #steak for dinner",
12
- "ugh! this #steak tasted like dog food"
13
- ]
14
  self.gt_topics = [["chilling"], ["steak"], ["steak"]]
15
 
16
  # add toy data for testing
17
  self.postly_instance.add_user("john")
18
- for i, post in enumerate(self.gt_posts):
19
- self.postly_instance.add_post("john", post, i)
20
-
21
  def test_add_user(self):
22
  assert "john" in self.postly_instance.userPosts
23
-
24
  def test_add_post(self):
25
  assert len(self.postly_instance.userPosts["john"]) == 3
26
 
@@ -37,10 +33,10 @@ class TestPlotlyClient:
37
  assert len(retrieved_posts) == 2
38
  for post in retrieved_posts:
39
  assert "#steak" in post
40
-
41
  def test_get_trending_topics(self):
42
  trending_topics = self.postly_instance.get_trending_topics(1, 3)
43
-
44
  assert len(trending_topics) == 2
45
  assert trending_topics == ["steak", "chilling"]
46
 
@@ -52,10 +48,10 @@ class TestPlotlyClient:
52
  def test_delete_user(self):
53
  temporary_postly_instance = PostlyClient()
54
  temporary_postly_instance.add_user("simon")
55
- temporary_postly_instance.add_post("simon", "just #coding today", 1)
56
 
57
  assert "simon" in temporary_postly_instance.userPosts
58
-
59
  temporary_postly_instance.delete_user("simon")
60
 
61
  assert "simon" not in temporary_postly_instance.userPosts
 
6
  self.postly_instance = PostlyClient()
7
 
8
  # define reference data for testing
9
+ self.gt_posts = ["just #chilling today", "eating #steak for dinner", "ugh! this #steak tasted like dog food"]
 
 
 
 
10
  self.gt_topics = [["chilling"], ["steak"], ["steak"]]
11
 
12
  # add toy data for testing
13
  self.postly_instance.add_user("john")
14
+ for post in self.gt_posts:
15
+ self.postly_instance.add_post("john", post)
16
+
17
  def test_add_user(self):
18
  assert "john" in self.postly_instance.userPosts
19
+
20
  def test_add_post(self):
21
  assert len(self.postly_instance.userPosts["john"]) == 3
22
 
 
33
  assert len(retrieved_posts) == 2
34
  for post in retrieved_posts:
35
  assert "#steak" in post
36
+
37
  def test_get_trending_topics(self):
38
  trending_topics = self.postly_instance.get_trending_topics(1, 3)
39
+
40
  assert len(trending_topics) == 2
41
  assert trending_topics == ["steak", "chilling"]
42
 
 
48
  def test_delete_user(self):
49
  temporary_postly_instance = PostlyClient()
50
  temporary_postly_instance.add_user("simon")
51
+ temporary_postly_instance.add_post("simon", "just #coding today")
52
 
53
  assert "simon" in temporary_postly_instance.userPosts
54
+
55
  temporary_postly_instance.delete_user("simon")
56
 
57
  assert "simon" not in temporary_postly_instance.userPosts