gp-flask 0.0.6__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.
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.4
2
+ Name: gp-flask
3
+ Version: 0.0.6
4
+ Summary: Some flask extensions for server side storage and other things
5
+ Author: Ender(Suzu)
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/endert1099/gpflask
8
+ Project-URL: Issues, https://github.com/endert1099/gpflask/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.13
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENCE
14
+ Requires-Dist: flask>=3.1.2
15
+ Dynamic: license-file
@@ -0,0 +1,8 @@
1
+ gp_flask-0.0.6.dist-info/licenses/LICENCE,sha256=oLnlWlQ1Xq5GmZhIWVe1timMuiBoN0Ei8wNSHnvT9_A,1054
2
+ gpflask/__init__.py,sha256=y10d4Prs4G5Msht5y-wcayLuN1SUNGNf7ZbkU12FjjE,101
3
+ gpflask/exceptions.py,sha256=yc_ScbIY9p9o1qDbhsC9Byc7JfTYTzmBbFHxeffayFo,244
4
+ gpflask/main.py,sha256=mMuaYB_RwSxrf2o0cAzIuQrkmCYYFxnmvqWlJj7nG38,6896
5
+ gp_flask-0.0.6.dist-info/METADATA,sha256=LUXphtvgjrqDL9yDSYpVA64syE2K6Js2rHjs4re1SyM,526
6
+ gp_flask-0.0.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
+ gp_flask-0.0.6.dist-info/top_level.txt,sha256=9tba6kDmYydvWxCT5new6XKS3cN_vWjCmyvJGtsUH-c,8
8
+ gp_flask-0.0.6.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,7 @@
1
+ Copyright 2025 Suzu :3
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1 @@
1
+ gpflask
gpflask/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+ from .main import DataPacket, GPFlask, ServerStoreException, LoadStorageException
2
+ from flask import *
gpflask/exceptions.py ADDED
@@ -0,0 +1,7 @@
1
+ class ServerStoreException(BaseException):
2
+ def __init__(self, *args: object) -> None:
3
+ super().__init__(*args)
4
+
5
+ class LoadStorageException(BaseException):
6
+ def __init__(self, *args: object) -> None:
7
+ super().__init__(*args)
gpflask/main.py ADDED
@@ -0,0 +1,155 @@
1
+ from os import PathLike
2
+ from os.path import join, exists
3
+ from flask import Flask, request
4
+ from typing import Any, Callable
5
+ from .exceptions import *
6
+ from time import time
7
+ from math import floor
8
+ import json
9
+ import traceback
10
+
11
+ class DataPacket:
12
+ def __init__(self, source: str, timestamp: int, data: dict[str, Any]):
13
+ self.source = source
14
+ self.timestamp = timestamp
15
+ self.data = data
16
+
17
+ def get_data(self, path: str | list[str]) -> Any | None:
18
+ if type(path) == str:
19
+ return self.data[path]
20
+ elif type(path) == list:
21
+ d = self.data
22
+ for p in path:
23
+ try:
24
+ d = d[p]
25
+ except IndexError:
26
+ return None
27
+ return d
28
+ return None
29
+
30
+ class GPFlask(Flask):
31
+ def __init__(self, import_name: str, static_url_path: str | None = None, static_folder: str | PathLike[str] | None = "static", static_host: str | None = None, host_matching: bool = False, subdomain_matching: bool = False, template_folder: str | PathLike[str] | None = "templates", instance_path: str | None = None, instance_relative_config: bool = False, root_path: str | None = None):
32
+ super().__init__(import_name, static_url_path, static_folder, static_host, host_matching, subdomain_matching, template_folder, instance_path, instance_relative_config, root_path)
33
+ self.storage: list[DataPacket] = []
34
+ self.named_storage: dict[str, dict[str, Any]] = {}
35
+
36
+ def get_request_host(self) -> str:
37
+ req_host = None
38
+ try:
39
+ req_host = join(request.host_url, request.path)
40
+ return req_host
41
+ except RuntimeError as e:
42
+ raise ServerStoreException(traceback.format_exc())
43
+
44
+ def store_packet(self, data: dict[str, Any]) -> int:
45
+ self.storage.append(DataPacket(self.get_request_host(), floor(time()), data))
46
+ return len(self.storage) - 1
47
+
48
+ def store_named_packet(self, name: str, data: dict[str, Any]) -> None:
49
+ self.named_storage.update({name: data})
50
+
51
+ def store_named_packet_safe(self, name: str, data: dict[str, Any]) -> None:
52
+ if self.named_storage[name]: return
53
+ self.named_storage.update({name: data})
54
+
55
+ def get_named_packet(self, name: str) -> dict[str, Any]:
56
+ return self.named_storage[name]
57
+
58
+ def get_packets_with_condition(self, fn: Callable[[DataPacket], bool]) -> list[DataPacket]:
59
+ return list(filter(fn, self.storage))
60
+
61
+ def get_packets_from_host(self, host: str) -> list[DataPacket]:
62
+ return self.get_packets_with_condition(lambda x: x.source == host)
63
+
64
+ def get_packets_before_time(self, timestamp: int) -> list[DataPacket]:
65
+ return self.get_packets_with_condition(lambda x: x.timestamp < timestamp)
66
+
67
+ def get_packets_after_time(self, timestamp: int) -> list[DataPacket]:
68
+ return self.get_packets_with_condition(lambda x: x.timestamp > timestamp)
69
+
70
+ def get_packets_during_time(self, timestamp: int) -> list[DataPacket]:
71
+ return self.get_packets_with_condition(lambda x: x.timestamp == timestamp)
72
+
73
+ def get_packets_before_during_time(self, timestamp: int) -> list[DataPacket]:
74
+ return self.get_packets_with_condition(lambda x: x.timestamp <= timestamp)
75
+
76
+ def get_packets_after_during_time(self, timestamp: int) -> list[DataPacket]:
77
+ return self.get_packets_with_condition(lambda x: x.timestamp >= timestamp)
78
+
79
+ def get_packets_between_time(self, begin_timestamp: int, end_timestamp: int) -> list[DataPacket]:
80
+ return self.get_packets_with_condition(lambda x: begin_timestamp < x.timestamp < end_timestamp)
81
+
82
+ def get_packets_between_during_time(self, begin_timestamp: int, end_timestamp: int) -> list[DataPacket]:
83
+ return self.get_packets_with_condition(lambda x: begin_timestamp <= x.timestamp <= end_timestamp)
84
+
85
+ def save_as_formatted_log(self, output_path: str) -> float:
86
+ s = time()
87
+ out = join(output_path, f"{floor(s)}.log")
88
+ if exists(out):
89
+ raise FileExistsError("A log has already been created at this timestamp. Are you saving your logs in a loop?")
90
+
91
+ data = "Named Storage:\n"
92
+ for v in self.named_storage:
93
+ data += f"{v}: {self.named_storage[v]}\n"
94
+
95
+ data += "\nUnnamed Storage:\n"
96
+ for v in self.storage:
97
+ data += f"Source: {v.source}\nTimestamp: {v.timestamp}\nData: {v.data}\n"
98
+
99
+ with open(out, "wt") as f:
100
+ f.write(data)
101
+
102
+ return time() - s
103
+
104
+ def save_as_formatted_log_append(self, output_path: str) -> float:
105
+ s = time()
106
+ out = join(output_path, f"{floor(s)}.log")
107
+ if exists(out):
108
+ raise FileExistsError("A log has already been created at this timestamp. Are you saving your logs in a loop?")
109
+
110
+ with open(out, "at") as f:
111
+ f.write("Named Storage:\n")
112
+ for v in self.named_storage:
113
+ with open(out, "at") as f:
114
+ data = f"{v}: {self.named_storage[v]}\n"
115
+ f.write(data)
116
+ with open(out, "at") as f:
117
+ f.write("\nUnnamed Storage:\n")
118
+ for v in self.storage:
119
+ with open(out, "at") as f:
120
+ data = f"Source: {v.source}\nTimestamp: {v.timestamp}\nData: {v.data}\n"
121
+ f.write(data)
122
+
123
+ return time() - s
124
+
125
+ def get_as_json(self, output_path: str) -> dict[str, list[DataPacket] | dict[str, dict[str, Any]]]:
126
+ return {"named_storage": self.named_storage, "unnamed_storage": self.storage}
127
+
128
+ def save_as_json(self, output_path: str) -> float:
129
+ s = time()
130
+ out = join(output_path, f"{floor(s)}.json")
131
+ if exists(out):
132
+ raise FileExistsError("A JSON file has already been created at this timestamp. Are you saving the file in a loop?")
133
+
134
+ data = {"named_storage": self.named_storage, "unnamed_storage": self.storage}
135
+ with open(out, "wt") as f:
136
+ f.write(json.dumps(data))
137
+
138
+ return time() - s
139
+
140
+ def load_from_json(self, input_path: str) -> float:
141
+ s = time()
142
+ if not exists(input_path):
143
+ raise FileNotFoundError("The JSON file doesn't exist")
144
+
145
+ with open(input_path, "rt") as f:
146
+ try:
147
+ data = json.loads(f.read())
148
+ if (not data["named_storage"]) or (not data["unnamed_storage"]):
149
+ raise LoadStorageException("The JSON file is missing 1 or more of the following items in the root object: \"named_storage\", \"unnamed_storage\"")
150
+ self.storage = data["unnamed_storage"]
151
+ self.named_storage = data["named_storage"]
152
+ except json.JSONDecodeError:
153
+ raise LoadStorageException("The JSON file contained invalid syntax. See traceback for more details.")
154
+
155
+ return time() - s