Skip to content

Commit bd9c0b9

Browse files
author
islekcaganmert
committed
Simpler Widgets, TheProtocols, New Links, Method Not Allowed
1 parent a270588 commit bd9c0b9

9 files changed

Lines changed: 129 additions & 89 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
dist
22
src/BevyFrame.egg-info
33
build
4-
venv
4+
.venv

.idea/bevyframe.iml

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# BevyFrame 0.2 ɑ
22

3-
Lightweight Python Web Framework
3+
Python Web Framework
44

55
***Upstream Version, Do Not Use in Production***
66

@@ -13,8 +13,8 @@ LuOS
1313

1414
Other
1515
```bash
16-
$ wget https://github.com/islekcaganmert/bevyframe/releases/download/Preview/BevyFrame-0.2.0-py3-none-any.whl
17-
$ python3 -m pip install ./BevyFrame-0.2.0-py3-none-any.whl
16+
$ wget https://github.com/islekcaganmert/bevyframe/releases/download/Preview/BevyFrame-0.3.0-py3-none-any.whl
17+
$ python3 -m pip install ./BevyFrame-0.3.0-py3-none-any.whl
1818
```
1919
## Features
2020

@@ -24,16 +24,16 @@ $ python3 -m pip install ./BevyFrame-0.2.0-py3-none-any.whl
2424
- Built-in decentralized authentication with [TheProtocols](https://github.com/islekcaganmert/TheProtocols)
2525
- Widget based templating engine
2626
- Routing engine for dynamic paths
27+
- Decentralized db-less user data with [TheProtocols](https://github.com/islekcaganmert/TheProtocols)
2728
- Decentralized user querying with [TheProtocols](https://github.com/islekcaganmert/TheProtocols)
28-
- JSON based CSS-like styling, importable from path, URL, dictionary
29+
- JSON based CSS-like styling, importable from any path, URL, in-code
2930
- User-friendly terminal output
3031
- Built-in error handling replaceable with a single file creation (ex. `404.py`)
3132
- Easy command line interface, `% python3 -m bevyframe config.json`
3233

3334
## Planned Features
3435

35-
- Decentralized cloud synced user data with [TheProtocols](https://github.com/islekcaganmert/TheProtocols)
36-
- Decentralized database with [TheProtocols](https://github.com/islekcaganmert/TheProtocols)
36+
- Built-in SQL Support
3737
- Page Authorization (Blacklist / Whitelist)
3838
- Easier Socket Integration
3939
- Easier REST API Development
@@ -49,4 +49,4 @@ $ python3 -m pip install ./BevyFrame-0.2.0-py3-none-any.whl
4949
- PyPI Releases: *Soon*
5050
- Source Code: https://github.com/islekcaganmert/bevyframe
5151
- Issue Tracker: https://github.com/islekcaganmert/bevyframe/issues
52-
- Community: https://www.hereus.net/communities/bevyframe.islekcaganmert.dev
52+
- Community: [!bevyframe@lemmy.today](https://lemmy.today/c/bevyframe)

pyproject.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
[project]
22
name = "BevyFrame"
3-
version = "0.2.0"
4-
description = "Lightweight Python Web Micro Framework"
3+
version = "0.3.0"
4+
description = "Python Web Framework"
55
readme = "README.md"
6-
license = {text = "LGPL-3.0"}
6+
license = {text = "LGPL-2.1"}
77
maintainers = [{name = "Çağan Mert İŞLEK", email = "islekcaganmert@gmail.com"}]
88
classifiers = [
99
"Environment :: Web Environment",
1010
"Intended Audience :: Developers",
11-
"License :: OSI Approved :: GPL-3.0 License",
11+
"License :: OSI Approved :: LGPL-2.1 License",
1212
"Operating System :: OS Independent",
1313
"Programming Language :: Python",
1414
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
1515
"Topic :: Internet :: WWW/HTTP :: Application",
1616
"Topic :: Software Development :: Libraries :: Application Frameworks",
1717
]
1818
requires-python = ">=3.9"
19-
dependencies = []
19+
dependencies = ["requests==2.32.3", "PyJWT==2.8.0", "TheProtocols==3.0.1"]
2020

2121
[project.urls]
2222
Donate = "https://www.buymeacoffee.com/islekcaganmert"
2323
Documentation = "https://github.com/islekcaganmert/bevyframe/wiki"
24-
Changes = "https://github.com/islekcaganmert/bevyframe/commits/main"
24+
Changes = "https://github.com/islekcaganmert/bevyframe/commits/master"
2525
"Source Code" = "https://github.com/islekcaganmert/bevyframe"
2626
"Issue Tracker" = "https://github.com/islekcaganmert/bevyframe/issues"
27-
Chat = "https://www.hereus.net/communities/bevyframe.islekcaganmert.dev"
27+
Chat = "https://lemmy.today/c/bevyframe"
2828

2929
[build-system]
3030
requires = ["setuptools","wheel"]

src/bevyframe/__init__.py

Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,49 @@
11
import urllib.parse
22
from datetime import datetime
3-
from random import randint
43
from typing import Any
54
import importlib.util
65
import importlib
76
import traceback
87
import getpass
98
import socket
10-
import json
11-
import sys
129
import os
1310
import re
1411
from .widgets import *
15-
from . import protocol
1612
from .login import *
13+
import requests
14+
import TheProtocols
15+
1716

1817
https_codes = {
19-
404: 'Not Found',
20-
500: 'Internal Server Error',
2118
200: 'OK',
19+
201: 'Created',
20+
202: 'Accepted',
21+
203: 'Non-Authoritative Information',
22+
204: 'No Content',
23+
205: 'Reset Content',
2224
301: 'Moved Permanently',
23-
303: 'See Other'
25+
302: 'Found',
26+
303: 'See Other',
27+
307: 'Temporary Redirect',
28+
308: 'Permanent Redirect',
29+
400: 'Bad Request',
30+
401: 'Unauthorized',
31+
402: 'Payment Required',
32+
403: 'Forbidden',
33+
405: 'Method Not Allowed',
34+
404: 'Not Found',
35+
410: 'Gone',
36+
415: 'Unsupported Media Type',
37+
418: 'I\'m a teapot',
38+
429: 'Too Many Requests',
39+
451: 'Unavailable For Legal Reasons',
40+
500: 'Internal Server Error',
41+
501: 'Not Implemented',
42+
502: 'Bad Gateway',
43+
503: 'Service Unavailable',
44+
504: 'Gateway Timeout',
45+
506: 'Variant Also Negotiates',
46+
511: 'Network Authentication Required'
2447
}
2548
admins = {}
2649
mime_types = {
@@ -64,6 +87,7 @@ def __init__(self, data: dict[str], app) -> None:
6487
try:
6588
self.email = data['credentials']['email']
6689
self.password = data['credentials']['password']
90+
self.user = TheProtocols.ID(self.email, self.password)
6791
except TypeError:
6892
pass
6993
self.app = app
@@ -82,17 +106,12 @@ class Response:
82106
def __init__(self, body: (Page, str, dict, list), **kwargs) -> None:
83107
self.body = body
84108
self.credentials = {}
85-
kwargs_info = {
86-
'status_code': [int, 200],
87-
'headers': [dict, {
88-
'Content-Type': 'text/html; charset=utf-8'
89-
}]
90-
}
109+
kwargs_info = ['status_code', 'headers']
110+
self.headers = {'Content-Type': 'text/html; charset=utf-8'}
111+
self.status_code = 200
91112
for kwarg in kwargs_info:
92113
if kwarg in kwargs:
93114
setattr(self, kwarg, kwargs_info[kwarg][0](kwargs[kwarg]))
94-
else:
95-
setattr(self, kwarg, kwargs_info[kwarg][1])
96115

97116
def login(self, email, password) -> None:
98117
self.credentials = {'email': email, 'password': password}
@@ -117,30 +136,33 @@ def __init__(self, package, developer, administrator, secret, style, icon='/favi
117136
self.routes = {}
118137
if isinstance(style, dict):
119138
self.style = style
120-
else:
139+
elif isinstance(style, str):
121140
if os.path.isfile(style):
122141
self.style = json.load(open(style, 'rb'))
123-
elif style.startswith('https://') or style.startswith('http://'):
124-
r = protocol.requests.get(style)
142+
elif style.startswith('https://'):
143+
r = requests.get(style)
125144
if r.status_code == 200:
126145
self.style = r.json()
146+
else:
147+
self.style = {}
148+
else:
149+
self.style = {}
150+
else:
151+
self.style = {}
127152
self.icon = icon
128153
self.keywords = keywords
129-
if not administrator:
130-
admins.update({self.package: protocol.get_admin(
131-
administrator,
132-
getpass.getpass(f'Password for {administrator}: '))
133-
})
154+
if administrator:
155+
self.admin = TheProtocols.ID(administrator, getpass.getpass(f'Password for {administrator}: '))
134156
print()
135-
admin = get_admin(package)
136-
print(f"Welcome {admin['name']} {admin['surname']}!")
157+
print(f"Welcome {self.admin.id}!")
137158
print()
138159

139-
def route(self, path) -> Any:
160+
def route(self, path, whitelist: list = None, blacklist: list = None) -> Any:
140161
def decorator(func) -> Any:
141162
self.routes.update({path: func})
142-
def wrapper(*args, **kwargs) -> Any:
143-
return func(*args, **kwargs)
163+
164+
def wrapper(r: Request, **kwargs) -> Any:
165+
return func(r, **kwargs)
144166
return wrapper
145167
return decorator
146168

@@ -205,7 +227,7 @@ def error_handler(self, request, status_code, exception) -> Response:
205227
title=https_codes[status_code],
206228
style=self.style,
207229
childs=e_boxes,
208-
selector=f'body_{current_user(request).settings.theme_color}'
230+
selector=f'body_{request.user.id.settings.theme_color}'
209231
),
210232
status_code=status_code
211233
)
@@ -279,8 +301,6 @@ def run(self, host: str = '127.0.0.1', port: int = 5000, debug: bool = True):
279301
page_script_path = page_script_path.replace('//', '/')
280302
if not os.path.isfile(page_script_path):
281303
page_script_path += '/__init__.py'
282-
if not os.path.isfile(page_script_path):
283-
resp = self.error_handler(Request(recv, self), 404, '')
284304
if os.path.isfile(page_script_path):
285305
if page_script_path.endswith('.py'):
286306
page_script_spec = importlib.util.spec_from_file_location(
@@ -290,7 +310,10 @@ def run(self, host: str = '127.0.0.1', port: int = 5000, debug: bool = True):
290310
page_script = importlib.util.module_from_spec(page_script_spec)
291311
try:
292312
page_script_spec.loader.exec_module(page_script)
293-
resp = getattr(page_script, recv['method'].lower())(Request(recv, self))
313+
if recv['method'].lower() in page_script.__dict__:
314+
resp = getattr(page_script, recv['method'].lower())(Request(recv, self))
315+
else:
316+
resp = self.error_handler(Request(recv, self), 405, '')
294317
except FileNotFoundError:
295318
resp = self.error_handler(Request(recv, self), 404, '')
296319
else:
@@ -306,7 +329,9 @@ def run(self, host: str = '127.0.0.1', port: int = 5000, debug: bool = True):
306329
'Connection': 'keep-alive'
307330
}
308331
)
309-
except Exception as e:
332+
else:
333+
resp = self.error_handler(Request(recv, self), 404, '')
334+
except Exception:
310335
resp = self.error_handler(Request(recv, self), 500, traceback.format_exc())
311336
if isinstance(resp, Page):
312337
resp.data['lang'] = ''

src/bevyframe/__main__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import sys
2-
import json
31
from bevyframe import *
42
import secrets
3+
import sys
54

65
config = {
76
'host': '127.0.0.1',

src/bevyframe/login.py

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from .protocol import Obj
2-
import requests
31
import jwt
42

53

@@ -10,22 +8,6 @@ def get_session_token(secret, email, password) -> str:
108
}, secret, algorithm='HS256')
119

1210

13-
def current_user(request) -> Obj:
14-
r = requests.post(
15-
f"https://{request.email.split('@')[1]}/protocols/current_user_info",
16-
data={
17-
'current_user_username': request.email.split('@')[0],
18-
'current_user_password': request.password
19-
}
20-
)
21-
if r.status_code == 200:
22-
r = r.json()
23-
r.update({'password': request.password})
24-
return Obj(r)
25-
else:
26-
return Obj({})
27-
28-
2911
def get_session(secret, token) -> dict:
3012
try:
3113
return jwt.decode(token, secret, algorithms=['HS256'])

0 commit comments

Comments
 (0)