platzky 0.1.19__py3-none-any.whl → 0.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
platzky/db/graph_ql_db.py CHANGED
@@ -1,22 +1,58 @@
1
- #TODO rename file, extract it to another library, remove qgl and aiohttp from dependencies
1
+ # TODO rename file, extract it to another library, remove qgl and aiohttp from dependencies
2
2
 
3
- from gql import gql, Client
3
+
4
+ from gql import Client, gql
4
5
  from gql.transport.aiohttp import AIOHTTPTransport
5
- import json
6
- from platzky.blog.db import DB
6
+ from pydantic import Field
7
+
8
+ from .db import DB, DBConfig
9
+ from ..models import Color, Post
10
+
11
+
12
+ def db_config_type():
13
+ return GraphQlDbConfig
14
+
15
+
16
+ class GraphQlDbConfig(DBConfig):
17
+ endpoint: str = Field(alias="CMS_ENDPOINT")
18
+ token: str = Field(alias="CMS_TOKEN")
19
+
7
20
 
21
+ def get_db(config: GraphQlDbConfig):
22
+ return GraphQL(config.endpoint, config.token)
8
23
 
9
- def get_db(config):
10
- endpoint = config["DB"]["CMS_ENDPOINT"]
11
- token = config["DB"]["CMS_TOKEN"]
12
- return GraphQL(endpoint, token)
24
+
25
+ def db_from_config(config: GraphQlDbConfig):
26
+ return GraphQL(config.endpoint, config.token)
27
+
28
+
29
+ def _standarize_post(post):
30
+ return {
31
+ "author": post["author"]["name"],
32
+ "slug": post["slug"],
33
+ "title": post["title"],
34
+ "excerpt": post["excerpt"],
35
+ "contentInMarkdown": post["contentInRichText"]["html"],
36
+ "comments": post["comments"],
37
+ "tags": post["tags"],
38
+ "language": post["language"],
39
+ "coverImage": {
40
+ "url": post["coverImage"]["image"]["url"],
41
+ },
42
+ "date": post["date"],
43
+ }
13
44
 
14
45
 
15
46
  class GraphQL(DB):
16
47
  def __init__(self, endpoint, token):
17
- full_token = 'bearer ' + token
18
- transport = AIOHTTPTransport(url=endpoint, headers={'Authorization': full_token})
48
+ self.module_name = "graph_ql_db"
49
+ self.db_name = "GraphQLDb"
50
+ full_token = "bearer " + token
51
+ transport = AIOHTTPTransport(
52
+ url=endpoint, headers={"Authorization": full_token}
53
+ )
19
54
  self.client = Client(transport=transport)
55
+ super().__init__()
20
56
 
21
57
  def get_all_posts(self, lang):
22
58
  all_posts = gql(
@@ -24,22 +60,38 @@ class GraphQL(DB):
24
60
  query MyQuery($lang: Lang!) {
25
61
  posts(where: {language: $lang}, orderBy: date_DESC, stage: PUBLISHED){
26
62
  createdAt
63
+ author {
64
+ name
65
+ }
66
+ contentInRichText {
67
+ html
68
+ }
69
+ comments {
70
+ comment
71
+ author
72
+ createdAt
73
+ }
27
74
  date
28
75
  title
29
76
  excerpt
30
77
  slug
31
78
  tags
79
+ language
32
80
  coverImage {
33
81
  alternateText
34
82
  image {
35
83
  url
36
84
  }
37
- }
85
+ }
38
86
  }
39
87
  }
40
88
  """
41
89
  )
42
- return self.client.execute(all_posts, variable_values={"lang": lang})['posts']
90
+ raw_ql_posts = self.client.execute(all_posts, variable_values={"lang": lang})[
91
+ "posts"
92
+ ]
93
+
94
+ return [Post.model_validate(_standarize_post(post)) for post in raw_ql_posts]
43
95
 
44
96
  def get_menu_items(self):
45
97
  menu_items = gql(
@@ -52,17 +104,23 @@ class GraphQL(DB):
52
104
  }
53
105
  """
54
106
  )
55
- return self.client.execute(menu_items)['menuItems']
107
+ return self.client.execute(menu_items)["menuItems"]
56
108
 
57
109
  def get_post(self, slug):
58
110
  post = gql(
59
111
  """
60
112
  query MyQuery($slug: String!) {
61
113
  post(where: {slug: $slug}, stage: PUBLISHED) {
114
+ date
115
+ language
62
116
  title
117
+ slug
118
+ author {
119
+ name
120
+ }
63
121
  contentInRichText {
64
- text
65
122
  markdown
123
+ html
66
124
  }
67
125
  excerpt
68
126
  tags
@@ -76,13 +134,16 @@ class GraphQL(DB):
76
134
  author
77
135
  comment
78
136
  date: createdAt
79
- }
137
+ }
80
138
  }
81
139
  }
82
- """)
83
- return self.client.execute(post, variable_values={"slug": slug})['post']
140
+ """
141
+ )
84
142
 
85
- #TODO Cleanup page logic of internationalization (now it depends on translation of slugs)
143
+ post_raw = self.client.execute(post, variable_values={"slug": slug})["post"]
144
+ return Post.model_validate(_standarize_post(post_raw))
145
+
146
+ # TODO Cleanup page logic of internationalization (now it depends on translation of slugs)
86
147
  def get_page(self, slug):
87
148
  post = gql(
88
149
  """
@@ -96,8 +157,9 @@ class GraphQL(DB):
96
157
  }
97
158
  }
98
159
  }
99
- """)
100
- return self.client.execute(post, variable_values={"slug": slug})['page']
160
+ """
161
+ )
162
+ return self.client.execute(post, variable_values={"slug": slug})["page"]
101
163
 
102
164
  def get_posts_by_tag(self, tag, lang):
103
165
  post = gql(
@@ -117,41 +179,11 @@ class GraphQL(DB):
117
179
  }
118
180
  }
119
181
  }
120
- """)
121
- return self.client.execute(post, variable_values={"tag": tag, "lang": lang})['posts']
122
-
123
- def get_all_providers(self):
124
- all_providers = gql(
125
- """
126
- query MyQuery {
127
- providers(stage: PUBLISHED) {
128
- link
129
- name
130
- offer
131
- currency
132
- }
133
- }
134
182
  """
135
183
  )
136
- providers = self.client.execute(all_providers)["providers"]
137
- for provider in providers:
138
- provider["offer"] = json.loads(provider["offer"])
139
- return providers
140
-
141
- def get_all_questions(self):
142
- all_questions = gql(
143
- """
144
- query MyQuery {
145
- questions(stage: PUBLISHED) {
146
- question
147
- field
148
- inputType
149
- }
150
- }
151
- """
152
- )
153
- query = self.client.execute(all_questions)
154
- return query['questions']
184
+ return self.client.execute(post, variable_values={"tag": tag, "lang": lang})[
185
+ "posts"
186
+ ]
155
187
 
156
188
  def add_comment(self, author_name, comment, post_slug):
157
189
  add_comment = gql(
@@ -167,7 +199,31 @@ class GraphQL(DB):
167
199
  id
168
200
  }
169
201
  }
170
- """)
171
- self.client.execute(add_comment, variable_values={
172
- "author": author_name, "comment": comment, "slug": post_slug
173
- })
202
+ """
203
+ )
204
+ self.client.execute(
205
+ add_comment,
206
+ variable_values={
207
+ "author": author_name,
208
+ "comment": comment,
209
+ "slug": post_slug,
210
+ },
211
+ )
212
+
213
+ def get_font(self):
214
+ return str("")
215
+
216
+ def get_logo_url(self):
217
+ return ""
218
+
219
+ def get_primary_color(self) -> Color:
220
+ return Color()
221
+
222
+ def get_secondary_color(self):
223
+ return Color()
224
+
225
+ def get_site_content(self):
226
+ return ""
227
+
228
+ def get_plugins_data(self):
229
+ return []
platzky/db/json_db.py CHANGED
@@ -1,46 +1,104 @@
1
- from platzky.blog.db import DB
2
1
  import datetime
2
+ from typing import Any, Dict
3
+
4
+ from pydantic import Field
5
+
6
+ from .db import DB, DBConfig
7
+ from ..models import MenuItem, Post
8
+
9
+
10
+ def db_config_type():
11
+ return JsonDbConfig
12
+
13
+
14
+ class JsonDbConfig(DBConfig):
15
+ data: Dict[str, Any] = Field(alias="DATA")
3
16
 
4
17
 
5
18
  def get_db(config):
6
- return Json(config["DATA"])
19
+ json_db_config = JsonDbConfig.model_validate(config)
20
+ return Json(json_db_config.data)
21
+
22
+
23
+ def db_from_config(config: JsonDbConfig):
24
+ return Json(config.data)
7
25
 
8
26
 
9
27
  class Json(DB):
10
- def __init__(self, data_dict):
11
- self.data = data_dict
28
+ def __init__(self, data: Dict[str, Any]):
29
+ super().__init__()
30
+ self.data: Dict[str, Any] = data
31
+ self.module_name = "json_db"
32
+ self.db_name = "JsonDb"
12
33
 
13
34
  def get_all_posts(self, lang):
14
- posts = (filter(lambda x: x["language"] == lang, self.data.get("posts", [])))
15
- return list(posts)
35
+ return [
36
+ Post.model_validate(post)
37
+ for post in self.get_site_content().get("posts", ())
38
+ if post["language"] == lang
39
+ ]
16
40
 
17
- def get_post(self, slug):
18
- post = next(filter(lambda x: x["slug"] == slug, self.data["posts"]), None)
19
- return post
41
+ def get_post(self, slug: str) -> Post:
42
+ """Returns a post matching the given slug."""
43
+ all_posts = self.get_site_content().get("posts")
44
+ if all_posts is None:
45
+ raise ValueError("Posts data is missing")
46
+ wanted_post = next((post for post in all_posts if post["slug"] == slug), None)
47
+ if wanted_post is None:
48
+ raise ValueError(f"Post with slug {slug} not found")
49
+ return Post.model_validate(wanted_post)
20
50
 
51
+ # TODO: add test for non-existing page
21
52
  def get_page(self, slug):
22
- post = next(filter(lambda x: x["slug"] == slug, self.data["pages"]), None)
23
- return post
53
+ list_of_pages = (
54
+ page
55
+ for page in self.get_site_content().get("pages")
56
+ if page["slug"] == slug
57
+ )
58
+ page = Post.model_validate(next(list_of_pages))
59
+ return page
24
60
 
25
- def get_menu_items(self):
26
- post = self.data.get("menu_items", [])
27
- return post
61
+ def get_menu_items(self) -> list[MenuItem]:
62
+ menu_items_raw = self.get_site_content().get("menu_items", [])
63
+ menu_items_list = [MenuItem.model_validate(x) for x in menu_items_raw]
64
+ return menu_items_list
28
65
 
29
66
  def get_posts_by_tag(self, tag, lang):
30
- posts = filter(lambda x: tag in x["tags"], self.data["posts"])
31
- return posts
67
+ return (
68
+ post for post in self.get_site_content()["posts"] if tag in post["tags"]
69
+ )
70
+
71
+ def get_site_content(self):
72
+ content = self.data.get("site_content")
73
+ if content is None:
74
+ raise Exception("Content should not be None")
75
+ return content
76
+
77
+ def get_logo_url(self):
78
+ return self.get_site_content().get("logo_url", "")
32
79
 
33
- def get_all_providers(self):
34
- return self.data["providers"]
80
+ def get_font(self) -> str:
81
+ return self.get_site_content().get("font", "")
35
82
 
36
- def get_all_questions(self):
37
- return self.data["questions"]
83
+ def get_primary_color(self):
84
+ return self.get_site_content().get("primary_color", "white")
85
+
86
+ def get_secondary_color(self):
87
+ return self.get_site_content().get("secondary_color", "navy")
38
88
 
39
89
  def add_comment(self, author_name, comment, post_slug):
40
90
  comment = {
41
91
  "author": str(author_name),
42
92
  "comment": str(comment),
43
- "date": datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
93
+ "date": datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S"),
44
94
  }
45
- post_index = next(i for i in range(len(self.data["posts"])) if self.data["posts"][i]["slug"] == post_slug)
46
- self.data["posts"][post_index]["comments"].append(comment)
95
+
96
+ post_index = next(
97
+ i
98
+ for i in range(len(self.get_site_content()["posts"]))
99
+ if self.get_site_content()["posts"][i]["slug"] == post_slug
100
+ )
101
+ self.get_site_content()["posts"][post_index]["comments"].append(comment)
102
+
103
+ def get_plugins_data(self):
104
+ return self.data.get("plugins", [])
@@ -1,25 +1,41 @@
1
1
  import json
2
- import os.path
3
2
 
4
- from platzky.db.json_db import Json
3
+ from pydantic import Field
4
+
5
+ from .db import DBConfig
6
+ from .json_db import Json
7
+
8
+
9
+ def db_config_type():
10
+ return JsonFileDbConfig
11
+
12
+
13
+ class JsonFileDbConfig(DBConfig):
14
+ path: str = Field(alias="PATH")
5
15
 
6
16
 
7
17
  def get_db(config):
8
- db_path = os.path.abspath(config["DB"]["PATH"])
9
- return JsonFile(db_path)
18
+ json_file_db_config = JsonFileDbConfig.model_validate(config)
19
+ return JsonFile(json_file_db_config.path)
20
+
21
+
22
+ def db_from_config(config: JsonFileDbConfig):
23
+ return JsonFile(config.path)
10
24
 
11
25
 
12
26
  class JsonFile(Json):
13
- def __init__(self, file_path):
14
- self.data_file_path = file_path
27
+ def __init__(self, path: str):
28
+ self.data_file_path = path
15
29
  with open(self.data_file_path) as json_file:
16
30
  data = json.load(json_file)
17
31
  super().__init__(data)
32
+ self.module_name = "json_file_db"
33
+ self.db_name = "JsonFileDb"
18
34
 
19
- def _save_file(self):
20
- with open(self.data_file_path, 'w') as json_file:
35
+ def __save_file(self):
36
+ with open(self.data_file_path, "w") as json_file:
21
37
  json.dump(self.data, json_file)
22
38
 
23
39
  def add_comment(self, author_name, comment, post_slug):
24
40
  super().add_comment(author_name, comment, post_slug)
25
- self._save_file()
41
+ self.__save_file()
platzky/models.py ADDED
@@ -0,0 +1,64 @@
1
+ from pydantic import BaseModel
2
+ import datetime
3
+ import humanize
4
+
5
+
6
+ class Image(BaseModel):
7
+ url: str = ""
8
+ alternateText: str = ""
9
+
10
+
11
+ class MenuItem(BaseModel):
12
+ name: str
13
+ url: str
14
+
15
+
16
+ class Comment(BaseModel):
17
+ author: str
18
+ comment: str
19
+ date: str # TODO change its type to datetime
20
+
21
+ @property
22
+ def time_delta(self) -> str:
23
+ now = datetime.datetime.now()
24
+ date = datetime.datetime.strptime(self.date.split(".")[0], "%Y-%m-%dT%H:%M:%S")
25
+ return humanize.naturaltime(now - date)
26
+
27
+
28
+ class Post(BaseModel):
29
+ author: str
30
+ slug: str
31
+ title: str
32
+ contentInMarkdown: str
33
+ comments: list[Comment]
34
+ excerpt: str
35
+ tags: list[str]
36
+ language: str
37
+ coverImage: Image
38
+ date: str
39
+
40
+ def __lt__(self, other):
41
+ if isinstance(other, Post):
42
+ return self.date < other.date
43
+ return NotImplemented
44
+
45
+
46
+ Page = Post
47
+
48
+
49
+ class Color(BaseModel):
50
+ def __init__(self, r: int = 0, g: int = 0, b: int = 0, a: int = 255):
51
+ if not (0 <= r <= 255):
52
+ raise ValueError("r must be between 0 and 255")
53
+ if not (0 <= g <= 255):
54
+ raise ValueError("g must be between 0 and 255")
55
+ if not (0 <= b <= 255):
56
+ raise ValueError("b must be between 0 and 255")
57
+ if not (0 <= a <= 255):
58
+ raise ValueError("a must be between 0 and 255")
59
+ super().__init__(r=r, g=g, b=b, a=a)
60
+
61
+ r: int
62
+ g: int
63
+ b: int
64
+ a: int