bafser 1.0.2__tar.gz

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.
Files changed (52) hide show
  1. bafser-1.0.2/.gitignore +4 -0
  2. bafser-1.0.2/LICENSE +21 -0
  3. bafser-1.0.2/PKG-INFO +205 -0
  4. bafser-1.0.2/README.md +184 -0
  5. bafser-1.0.2/pyproject.toml +35 -0
  6. bafser-1.0.2/src/bafser/__init__.py +48 -0
  7. bafser-1.0.2/src/bafser/app.py +237 -0
  8. bafser-1.0.2/src/bafser/bfs_config.example.py +16 -0
  9. bafser-1.0.2/src/bafser/cli.py +30 -0
  10. bafser-1.0.2/src/bafser/data/__init__.py +0 -0
  11. bafser-1.0.2/src/bafser/data/_roles.py +39 -0
  12. bafser-1.0.2/src/bafser/data/_tables.py +5 -0
  13. bafser-1.0.2/src/bafser/data/image.py +109 -0
  14. bafser-1.0.2/src/bafser/data/log.py +154 -0
  15. bafser-1.0.2/src/bafser/data/operation.py +38 -0
  16. bafser-1.0.2/src/bafser/data/permission.py +18 -0
  17. bafser-1.0.2/src/bafser/data/role.py +128 -0
  18. bafser-1.0.2/src/bafser/data/user.py +181 -0
  19. bafser-1.0.2/src/bafser/data/user_role.py +50 -0
  20. bafser-1.0.2/src/bafser/db_session.py +69 -0
  21. bafser-1.0.2/src/bafser/logger.py +213 -0
  22. bafser-1.0.2/src/bafser/readme.md +184 -0
  23. bafser-1.0.2/src/bafser/scripts/add_user.py +29 -0
  24. bafser-1.0.2/src/bafser/scripts/add_user_role.py +33 -0
  25. bafser-1.0.2/src/bafser/scripts/change_user_password.py +22 -0
  26. bafser-1.0.2/src/bafser/scripts/init_db_values.py +20 -0
  27. bafser-1.0.2/src/bafser/scripts/remove_user_role.py +33 -0
  28. bafser-1.0.2/src/bafser/scripts/update_roles_permissions.py +13 -0
  29. bafser-1.0.2/src/bafser/table_base.py +69 -0
  30. bafser-1.0.2/src/bafser/utils/__init__.py +24 -0
  31. bafser-1.0.2/src/bafser/utils/create_file_response.py +13 -0
  32. bafser-1.0.2/src/bafser/utils/create_folder_for_file.py +7 -0
  33. bafser-1.0.2/src/bafser/utils/get_all_vars.py +10 -0
  34. bafser-1.0.2/src/bafser/utils/get_datetime_now.py +5 -0
  35. bafser-1.0.2/src/bafser/utils/get_json.py +13 -0
  36. bafser-1.0.2/src/bafser/utils/get_json_list_from_req.py +14 -0
  37. bafser-1.0.2/src/bafser/utils/get_json_values.py +28 -0
  38. bafser-1.0.2/src/bafser/utils/get_json_values_from_req.py +20 -0
  39. bafser-1.0.2/src/bafser/utils/get_secret_key.py +21 -0
  40. bafser-1.0.2/src/bafser/utils/import_all_tables.py +18 -0
  41. bafser-1.0.2/src/bafser/utils/ip_to_emoji.py +26 -0
  42. bafser-1.0.2/src/bafser/utils/jsonify_list.py +5 -0
  43. bafser-1.0.2/src/bafser/utils/parse_date.py +10 -0
  44. bafser-1.0.2/src/bafser/utils/permission_required.py +52 -0
  45. bafser-1.0.2/src/bafser/utils/randstr.py +8 -0
  46. bafser-1.0.2/src/bafser/utils/register_blueprints.py +12 -0
  47. bafser-1.0.2/src/bafser/utils/response_msg.py +7 -0
  48. bafser-1.0.2/src/bafser/utils/response_not_found.py +5 -0
  49. bafser-1.0.2/src/bafser/utils/use_db_session.py +17 -0
  50. bafser-1.0.2/src/bafser/utils/use_user.py +37 -0
  51. bafser-1.0.2/src/bafser/utils/use_userId.py +43 -0
  52. bafser-1.0.2/src/bafser/utils/use_user_optional.py +35 -0
@@ -0,0 +1,4 @@
1
+ .venv/
2
+ __pycache__/
3
+ build/
4
+ dist/
bafser-1.0.2/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 MixelTe
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
bafser-1.0.2/PKG-INFO ADDED
@@ -0,0 +1,205 @@
1
+ Metadata-Version: 2.4
2
+ Name: bafser
3
+ Version: 1.0.2
4
+ Summary: Base for flask server
5
+ Project-URL: Homepage, https://github.com/MixelTe/bafser
6
+ Project-URL: Issues, https://github.com/MixelTe/bafser/issues
7
+ Author: Mixel Te
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Requires-Python: ==3.9.*
13
+ Requires-Dist: flask-jwt-extended==4.5.2
14
+ Requires-Dist: flask==2.1.2
15
+ Requires-Dist: pyjwt<2.10
16
+ Requires-Dist: pymysql==1.1.1
17
+ Requires-Dist: sqlalchemy-serializer==1.4.1
18
+ Requires-Dist: sqlalchemy==2.0.19
19
+ Requires-Dist: werkzeug==2.3.6
20
+ Description-Content-Type: text/markdown
21
+
22
+ # base for flask server by Mixel Te
23
+
24
+ ## requirements.txt
25
+ Python 3.9.5
26
+ ```
27
+ flask==2.1.2
28
+ sqlalchemy==2.0.19
29
+ werkzeug==2.3.6
30
+ sqlalchemy_serializer==1.4.1
31
+ pyjwt<2.10
32
+ flask_jwt_extended==4.5.2
33
+ PyMySQL==1.1.1
34
+ ```
35
+
36
+ ## usage
37
+ copy `bfs_config.example.py` to project root as `bfs_config.py`
38
+
39
+ create files:
40
+
41
+ .gitignore
42
+ ```
43
+ .venv
44
+ *__pycache__*
45
+ logs/
46
+ db/
47
+ /images
48
+ /fonts
49
+ secret_key_jwt.txt
50
+ ```
51
+
52
+ ```py
53
+ # data/_operations.py
54
+ from bfs import OperationsBase
55
+
56
+
57
+ class Operations(OperationsBase):
58
+ oper_id = ("oper_id", "Operation description")
59
+ oper_id2 = ("oper_id2", "Operation description")
60
+ ...
61
+ ```
62
+ ```py
63
+ # data/_roles.py
64
+ from bfs import RolesBase
65
+ from data._operations import Operations
66
+
67
+
68
+ class Roles(RolesBase):
69
+ role_name = 2
70
+ role_name2 = 3
71
+ ...
72
+
73
+
74
+ Roles.ROLES = {
75
+ Roles.role_name: {
76
+ "name": "Role name",
77
+ "operations": [
78
+ Operations.oper_id,
79
+ Operations.oper_id2,
80
+ ]
81
+ },
82
+ Roles.role_name2: {
83
+ "name": "Role name 2",
84
+ "operations": [
85
+ Operations.oper_id,
86
+ ]
87
+ },
88
+ }
89
+ ```
90
+ ```py
91
+ # data/_tables.py
92
+ from bfs import TablesBase
93
+
94
+
95
+ class Tables(TablesBase):
96
+ TableName = "TableName"
97
+ AnotherTableName = "AnotherTableName"
98
+ ```
99
+ ```py
100
+ # data/some_table.py
101
+ from bfs import SqlAlchemyBase, ObjMixin
102
+ from data._tables import Tables
103
+
104
+
105
+ class SomeTable(SqlAlchemyBase, ObjMixin):
106
+ __tablename__ = Tables.SomeTable
107
+ ...
108
+
109
+ ```
110
+ * `IdMixin` adds `id` column
111
+ * `ObjMixin` adds `id` and `deleted` columns
112
+
113
+ ```py
114
+ # main.py
115
+ import sys
116
+ from bfs import AppConfig, create_app
117
+ from scripts.init_dev_values import init_dev_values
118
+
119
+
120
+ app, run = create_app(__name__, AppConfig(
121
+ MESSAGE_TO_FRONTEND="",
122
+ DEV_MODE="dev" in sys.argv,
123
+ DELAY_MODE="delay" in sys.argv,
124
+ )
125
+ .add_data_folder("FONTS_FOLDER", "fonts")
126
+ .add_secret_key("API_SECRET_KEY", "secret_key_api.txt")
127
+ )
128
+
129
+ run(__name__ == "__main__", lambda: init_dev_values(True), port=5001)
130
+ ```
131
+
132
+ ### modifying User and Image
133
+ User:
134
+ ```py
135
+ from sqlalchemy import Column, String
136
+ from sqlalchemy.orm import Session
137
+
138
+ from bfs import UserBase
139
+ from data._roles import Roles
140
+
141
+
142
+ class User(UserBase):
143
+ newColumn = Column(String)
144
+
145
+ @classmethod
146
+ def new(cls, creator: "User", login: str, password: str, name: str, roles: list[int], newColumn: str, db_sess: Session = None) -> "User":
147
+ return super().new(creator, login, password, name, roles, db_sess, newColumn=newColumn)
148
+
149
+ @staticmethod
150
+ def _new(db_sess: Session, user_kwargs: dict, newColumn: str):
151
+ user = User(**user_kwargs, newColumn=newColumn)
152
+ changes = [("newColumn", newColumn)]
153
+ return user, changes
154
+
155
+ @staticmethod
156
+ def create_admin(db_sess: Session):
157
+ fake_creator = User.get_fake_system()
158
+ return User.new(fake_creator, "admin", "admin", "Админ", [Roles.admin], "newColumnValue", db_sess=db_sess)
159
+
160
+ ```
161
+ Image:
162
+ ```py
163
+ # to use relationship you must name the file something other than image.py
164
+ # img.py for the example, because of the way sqlalchemy finds classes
165
+ image = orm.relationship("data.img.Image")
166
+ ```
167
+ ```py
168
+ from typing import TypedDict, Union
169
+ from sqlalchemy import Column, String
170
+
171
+ from bfs import Image as ImageBase, get_json_values
172
+ from data.user import User
173
+
174
+
175
+ class ImageJson(TypedDict):
176
+ data: str
177
+ name: str
178
+ newColumnData: str
179
+
180
+
181
+ TError = str
182
+
183
+
184
+ class Image(ImageBase):
185
+ newColumn = Column(String)
186
+
187
+ @classmethod
188
+ def new(cls, creator: User, json: ImageJson) -> Union[tuple[None, TError], tuple["Image", None]]:
189
+ return super().new(creator, json)
190
+
191
+ @staticmethod
192
+ def _new(creator: User, json: ImageJson, image_kwargs):
193
+ newColumnData, values_error = get_json_values(json, ("newColumnData", None))
194
+ if values_error:
195
+ return None, None, values_error
196
+
197
+ img = Image(**image_kwargs, newColumn=newColumnData)
198
+ changes = [("newColumn", newColumnData)]
199
+ return img, changes, None
200
+ ```
201
+
202
+ #### csv header for requests log
203
+ ```csv
204
+ reqid;ip;uid;asctime;method;url;level;message;code;json
205
+ ```
bafser-1.0.2/README.md ADDED
@@ -0,0 +1,184 @@
1
+ # base for flask server by Mixel Te
2
+
3
+ ## requirements.txt
4
+ Python 3.9.5
5
+ ```
6
+ flask==2.1.2
7
+ sqlalchemy==2.0.19
8
+ werkzeug==2.3.6
9
+ sqlalchemy_serializer==1.4.1
10
+ pyjwt<2.10
11
+ flask_jwt_extended==4.5.2
12
+ PyMySQL==1.1.1
13
+ ```
14
+
15
+ ## usage
16
+ copy `bfs_config.example.py` to project root as `bfs_config.py`
17
+
18
+ create files:
19
+
20
+ .gitignore
21
+ ```
22
+ .venv
23
+ *__pycache__*
24
+ logs/
25
+ db/
26
+ /images
27
+ /fonts
28
+ secret_key_jwt.txt
29
+ ```
30
+
31
+ ```py
32
+ # data/_operations.py
33
+ from bfs import OperationsBase
34
+
35
+
36
+ class Operations(OperationsBase):
37
+ oper_id = ("oper_id", "Operation description")
38
+ oper_id2 = ("oper_id2", "Operation description")
39
+ ...
40
+ ```
41
+ ```py
42
+ # data/_roles.py
43
+ from bfs import RolesBase
44
+ from data._operations import Operations
45
+
46
+
47
+ class Roles(RolesBase):
48
+ role_name = 2
49
+ role_name2 = 3
50
+ ...
51
+
52
+
53
+ Roles.ROLES = {
54
+ Roles.role_name: {
55
+ "name": "Role name",
56
+ "operations": [
57
+ Operations.oper_id,
58
+ Operations.oper_id2,
59
+ ]
60
+ },
61
+ Roles.role_name2: {
62
+ "name": "Role name 2",
63
+ "operations": [
64
+ Operations.oper_id,
65
+ ]
66
+ },
67
+ }
68
+ ```
69
+ ```py
70
+ # data/_tables.py
71
+ from bfs import TablesBase
72
+
73
+
74
+ class Tables(TablesBase):
75
+ TableName = "TableName"
76
+ AnotherTableName = "AnotherTableName"
77
+ ```
78
+ ```py
79
+ # data/some_table.py
80
+ from bfs import SqlAlchemyBase, ObjMixin
81
+ from data._tables import Tables
82
+
83
+
84
+ class SomeTable(SqlAlchemyBase, ObjMixin):
85
+ __tablename__ = Tables.SomeTable
86
+ ...
87
+
88
+ ```
89
+ * `IdMixin` adds `id` column
90
+ * `ObjMixin` adds `id` and `deleted` columns
91
+
92
+ ```py
93
+ # main.py
94
+ import sys
95
+ from bfs import AppConfig, create_app
96
+ from scripts.init_dev_values import init_dev_values
97
+
98
+
99
+ app, run = create_app(__name__, AppConfig(
100
+ MESSAGE_TO_FRONTEND="",
101
+ DEV_MODE="dev" in sys.argv,
102
+ DELAY_MODE="delay" in sys.argv,
103
+ )
104
+ .add_data_folder("FONTS_FOLDER", "fonts")
105
+ .add_secret_key("API_SECRET_KEY", "secret_key_api.txt")
106
+ )
107
+
108
+ run(__name__ == "__main__", lambda: init_dev_values(True), port=5001)
109
+ ```
110
+
111
+ ### modifying User and Image
112
+ User:
113
+ ```py
114
+ from sqlalchemy import Column, String
115
+ from sqlalchemy.orm import Session
116
+
117
+ from bfs import UserBase
118
+ from data._roles import Roles
119
+
120
+
121
+ class User(UserBase):
122
+ newColumn = Column(String)
123
+
124
+ @classmethod
125
+ def new(cls, creator: "User", login: str, password: str, name: str, roles: list[int], newColumn: str, db_sess: Session = None) -> "User":
126
+ return super().new(creator, login, password, name, roles, db_sess, newColumn=newColumn)
127
+
128
+ @staticmethod
129
+ def _new(db_sess: Session, user_kwargs: dict, newColumn: str):
130
+ user = User(**user_kwargs, newColumn=newColumn)
131
+ changes = [("newColumn", newColumn)]
132
+ return user, changes
133
+
134
+ @staticmethod
135
+ def create_admin(db_sess: Session):
136
+ fake_creator = User.get_fake_system()
137
+ return User.new(fake_creator, "admin", "admin", "Админ", [Roles.admin], "newColumnValue", db_sess=db_sess)
138
+
139
+ ```
140
+ Image:
141
+ ```py
142
+ # to use relationship you must name the file something other than image.py
143
+ # img.py for the example, because of the way sqlalchemy finds classes
144
+ image = orm.relationship("data.img.Image")
145
+ ```
146
+ ```py
147
+ from typing import TypedDict, Union
148
+ from sqlalchemy import Column, String
149
+
150
+ from bfs import Image as ImageBase, get_json_values
151
+ from data.user import User
152
+
153
+
154
+ class ImageJson(TypedDict):
155
+ data: str
156
+ name: str
157
+ newColumnData: str
158
+
159
+
160
+ TError = str
161
+
162
+
163
+ class Image(ImageBase):
164
+ newColumn = Column(String)
165
+
166
+ @classmethod
167
+ def new(cls, creator: User, json: ImageJson) -> Union[tuple[None, TError], tuple["Image", None]]:
168
+ return super().new(creator, json)
169
+
170
+ @staticmethod
171
+ def _new(creator: User, json: ImageJson, image_kwargs):
172
+ newColumnData, values_error = get_json_values(json, ("newColumnData", None))
173
+ if values_error:
174
+ return None, None, values_error
175
+
176
+ img = Image(**image_kwargs, newColumn=newColumnData)
177
+ changes = [("newColumn", newColumnData)]
178
+ return img, changes, None
179
+ ```
180
+
181
+ #### csv header for requests log
182
+ ```csv
183
+ reqid;ip;uid;asctime;method;url;level;message;code;json
184
+ ```
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["hatchling >= 1.26"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "bafser"
7
+ version = "1.0.2"
8
+ authors = [
9
+ { name = "Mixel Te" },
10
+ ]
11
+ description = "Base for flask server"
12
+ readme = "README.md"
13
+ requires-python = "== 3.9.*"
14
+ classifiers = [
15
+ "Programming Language :: Python :: 3.9",
16
+ "Operating System :: OS Independent",
17
+ ]
18
+ license = "MIT"
19
+ license-files = ["LICEN[CS]E*"]
20
+ dependencies = [
21
+ "flask == 2.1.2",
22
+ "sqlalchemy == 2.0.19",
23
+ "werkzeug == 2.3.6",
24
+ "sqlalchemy_serializer == 1.4.1",
25
+ "pyjwt < 2.10",
26
+ "flask_jwt_extended == 4.5.2",
27
+ "PyMySQL == 1.1.1",
28
+ ]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/MixelTe/bafser"
32
+ Issues = "https://github.com/MixelTe/bafser/issues"
33
+
34
+ [project.scripts]
35
+ bafser = "bafser:cli"
@@ -0,0 +1,48 @@
1
+ # base for flask server by Mixel Te
2
+
3
+ from .utils.response_msg import response_msg
4
+ from .utils.get_json_values import get_json_values
5
+
6
+ from .utils.create_file_response import create_file_response
7
+ from .utils.create_folder_for_file import create_folder_for_file
8
+ from .utils.get_datetime_now import get_datetime_now
9
+ from .utils.get_json import get_json
10
+ from .utils.get_json_list_from_req import get_json_list_from_req
11
+ from .utils.get_json_values_from_req import get_json_values_from_req
12
+ from .utils.ip_to_emoji import ip_to_emoji, emoji_to_ip
13
+ from .utils.jsonify_list import jsonify_list
14
+ from .utils.parse_date import parse_date
15
+ from .utils.permission_required import create_permission_required_decorator
16
+ from .utils.permission_required import permission_required, permission_required_any
17
+ from .utils.randstr import randstr
18
+ from .utils.response_not_found import response_not_found
19
+ from .utils.use_db_session import use_db_session
20
+ from .utils.use_userId import use_userId, use_userId_optional
21
+ from .utils.use_user import use_user
22
+ from .utils.use_user_optional import use_user_optional
23
+
24
+ from .app import AppConfig, create_app
25
+ from .logger import get_logger_frontend, log_frontend_error, get_log_fpath, add_file_logger, ParametrizedLogger
26
+
27
+ from .db_session import SqlAlchemyBase
28
+ from .table_base import TableBase, IdMixin, ObjMixin
29
+ from .data._tables import TablesBase
30
+ from .data._roles import RolesBase
31
+ from .data.operation import OperationsBase
32
+ from .data.user_role import UserRole
33
+ from .data.user import UserBase
34
+ from .data.log import Log
35
+ from .data.role import Role
36
+ from .data.image import Image
37
+
38
+ from .scripts.init_db_values import init_db_values
39
+
40
+
41
+ class M:
42
+ DELETE = "DELETE"
43
+ GET = "GET"
44
+ HEAD = "HEAD"
45
+ OPTIONS = "OPTIONS"
46
+ PATCH = "PATCH"
47
+ POST = "POST"
48
+ PUT = "PUT"