Skip to content

Commit

Permalink
Simpler Widgets, TheProtocols, New Links, Method Not Allowed
Browse files Browse the repository at this point in the history
  • Loading branch information
islekcaganmert committed Jun 15, 2024
1 parent a270588 commit bd9c0b9
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 89 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
dist
src/BevyFrame.egg-info
build
venv
.venv
7 changes: 6 additions & 1 deletion .idea/bevyframe.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# BevyFrame 0.2 ɑ

Lightweight Python Web Framework
Python Web Framework

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

Expand All @@ -13,8 +13,8 @@ LuOS

Other
```bash
$ wget https://github.com/islekcaganmert/bevyframe/releases/download/Preview/BevyFrame-0.2.0-py3-none-any.whl
$ python3 -m pip install ./BevyFrame-0.2.0-py3-none-any.whl
$ wget https://github.com/islekcaganmert/bevyframe/releases/download/Preview/BevyFrame-0.3.0-py3-none-any.whl
$ python3 -m pip install ./BevyFrame-0.3.0-py3-none-any.whl
```
## Features

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

## Planned Features

- Decentralized cloud synced user data with [TheProtocols](https://github.com/islekcaganmert/TheProtocols)
- Decentralized database with [TheProtocols](https://github.com/islekcaganmert/TheProtocols)
- Built-in SQL Support
- Page Authorization (Blacklist / Whitelist)
- Easier Socket Integration
- Easier REST API Development
Expand All @@ -49,4 +49,4 @@ $ python3 -m pip install ./BevyFrame-0.2.0-py3-none-any.whl
- PyPI Releases: *Soon*
- Source Code: https://github.com/islekcaganmert/bevyframe
- Issue Tracker: https://github.com/islekcaganmert/bevyframe/issues
- Community: https://www.hereus.net/communities/bevyframe.islekcaganmert.dev
- Community: [![email protected]](https://lemmy.today/c/bevyframe)
14 changes: 7 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
[project]
name = "BevyFrame"
version = "0.2.0"
description = "Lightweight Python Web Micro Framework"
version = "0.3.0"
description = "Python Web Framework"
readme = "README.md"
license = {text = "LGPL-3.0"}
license = {text = "LGPL-2.1"}
maintainers = [{name = "Çağan Mert İŞLEK", email = "[email protected]"}]
classifiers = [
"Environment :: Web Environment",
"Intended Audience :: Developers",
"License :: OSI Approved :: GPL-3.0 License",
"License :: OSI Approved :: LGPL-2.1 License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
"Topic :: Internet :: WWW/HTTP :: Application",
"Topic :: Software Development :: Libraries :: Application Frameworks",
]
requires-python = ">=3.9"
dependencies = []
dependencies = ["requests==2.32.3", "PyJWT==2.8.0", "TheProtocols==3.0.1"]

[project.urls]
Donate = "https://www.buymeacoffee.com/islekcaganmert"
Documentation = "https://github.com/islekcaganmert/bevyframe/wiki"
Changes = "https://github.com/islekcaganmert/bevyframe/commits/main"
Changes = "https://github.com/islekcaganmert/bevyframe/commits/master"
"Source Code" = "https://github.com/islekcaganmert/bevyframe"
"Issue Tracker" = "https://github.com/islekcaganmert/bevyframe/issues"
Chat = "https://www.hereus.net/communities/bevyframe.islekcaganmert.dev"
Chat = "https://lemmy.today/c/bevyframe"

[build-system]
requires = ["setuptools","wheel"]
Expand Down
91 changes: 58 additions & 33 deletions src/bevyframe/__init__.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,49 @@
import urllib.parse
from datetime import datetime
from random import randint
from typing import Any
import importlib.util
import importlib
import traceback
import getpass
import socket
import json
import sys
import os
import re
from .widgets import *
from . import protocol
from .login import *
import requests
import TheProtocols


https_codes = {
404: 'Not Found',
500: 'Internal Server Error',
200: 'OK',
201: 'Created',
202: 'Accepted',
203: 'Non-Authoritative Information',
204: 'No Content',
205: 'Reset Content',
301: 'Moved Permanently',
303: 'See Other'
302: 'Found',
303: 'See Other',
307: 'Temporary Redirect',
308: 'Permanent Redirect',
400: 'Bad Request',
401: 'Unauthorized',
402: 'Payment Required',
403: 'Forbidden',
405: 'Method Not Allowed',
404: 'Not Found',
410: 'Gone',
415: 'Unsupported Media Type',
418: 'I\'m a teapot',
429: 'Too Many Requests',
451: 'Unavailable For Legal Reasons',
500: 'Internal Server Error',
501: 'Not Implemented',
502: 'Bad Gateway',
503: 'Service Unavailable',
504: 'Gateway Timeout',
506: 'Variant Also Negotiates',
511: 'Network Authentication Required'
}
admins = {}
mime_types = {
Expand Down Expand Up @@ -64,6 +87,7 @@ def __init__(self, data: dict[str], app) -> None:
try:
self.email = data['credentials']['email']
self.password = data['credentials']['password']
self.user = TheProtocols.ID(self.email, self.password)
except TypeError:
pass
self.app = app
Expand All @@ -82,17 +106,12 @@ class Response:
def __init__(self, body: (Page, str, dict, list), **kwargs) -> None:
self.body = body
self.credentials = {}
kwargs_info = {
'status_code': [int, 200],
'headers': [dict, {
'Content-Type': 'text/html; charset=utf-8'
}]
}
kwargs_info = ['status_code', 'headers']
self.headers = {'Content-Type': 'text/html; charset=utf-8'}
self.status_code = 200
for kwarg in kwargs_info:
if kwarg in kwargs:
setattr(self, kwarg, kwargs_info[kwarg][0](kwargs[kwarg]))
else:
setattr(self, kwarg, kwargs_info[kwarg][1])

def login(self, email, password) -> None:
self.credentials = {'email': email, 'password': password}
Expand All @@ -117,30 +136,33 @@ def __init__(self, package, developer, administrator, secret, style, icon='/favi
self.routes = {}
if isinstance(style, dict):
self.style = style
else:
elif isinstance(style, str):
if os.path.isfile(style):
self.style = json.load(open(style, 'rb'))
elif style.startswith('https://') or style.startswith('http://'):
r = protocol.requests.get(style)
elif style.startswith('https://'):
r = requests.get(style)
if r.status_code == 200:
self.style = r.json()
else:
self.style = {}
else:
self.style = {}
else:
self.style = {}
self.icon = icon
self.keywords = keywords
if not administrator:
admins.update({self.package: protocol.get_admin(
administrator,
getpass.getpass(f'Password for {administrator}: '))
})
if administrator:
self.admin = TheProtocols.ID(administrator, getpass.getpass(f'Password for {administrator}: '))
print()
admin = get_admin(package)
print(f"Welcome {admin['name']} {admin['surname']}!")
print(f"Welcome {self.admin.id}!")
print()

def route(self, path) -> Any:
def route(self, path, whitelist: list = None, blacklist: list = None) -> Any:
def decorator(func) -> Any:
self.routes.update({path: func})
def wrapper(*args, **kwargs) -> Any:
return func(*args, **kwargs)

def wrapper(r: Request, **kwargs) -> Any:
return func(r, **kwargs)
return wrapper
return decorator

Expand Down Expand Up @@ -205,7 +227,7 @@ def error_handler(self, request, status_code, exception) -> Response:
title=https_codes[status_code],
style=self.style,
childs=e_boxes,
selector=f'body_{current_user(request).settings.theme_color}'
selector=f'body_{request.user.id.settings.theme_color}'
),
status_code=status_code
)
Expand Down Expand Up @@ -279,8 +301,6 @@ def run(self, host: str = '127.0.0.1', port: int = 5000, debug: bool = True):
page_script_path = page_script_path.replace('//', '/')
if not os.path.isfile(page_script_path):
page_script_path += '/__init__.py'
if not os.path.isfile(page_script_path):
resp = self.error_handler(Request(recv, self), 404, '')
if os.path.isfile(page_script_path):
if page_script_path.endswith('.py'):
page_script_spec = importlib.util.spec_from_file_location(
Expand All @@ -290,7 +310,10 @@ def run(self, host: str = '127.0.0.1', port: int = 5000, debug: bool = True):
page_script = importlib.util.module_from_spec(page_script_spec)
try:
page_script_spec.loader.exec_module(page_script)
resp = getattr(page_script, recv['method'].lower())(Request(recv, self))
if recv['method'].lower() in page_script.__dict__:
resp = getattr(page_script, recv['method'].lower())(Request(recv, self))
else:
resp = self.error_handler(Request(recv, self), 405, '')
except FileNotFoundError:
resp = self.error_handler(Request(recv, self), 404, '')
else:
Expand All @@ -306,7 +329,9 @@ def run(self, host: str = '127.0.0.1', port: int = 5000, debug: bool = True):
'Connection': 'keep-alive'
}
)
except Exception as e:
else:
resp = self.error_handler(Request(recv, self), 404, '')
except Exception:
resp = self.error_handler(Request(recv, self), 500, traceback.format_exc())
if isinstance(resp, Page):
resp.data['lang'] = ''
Expand Down
3 changes: 1 addition & 2 deletions src/bevyframe/__main__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import sys
import json
from bevyframe import *
import secrets
import sys

config = {
'host': '127.0.0.1',
Expand Down
18 changes: 0 additions & 18 deletions src/bevyframe/login.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from .protocol import Obj
import requests
import jwt


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


def current_user(request) -> Obj:
r = requests.post(
f"https://{request.email.split('@')[1]}/protocols/current_user_info",
data={
'current_user_username': request.email.split('@')[0],
'current_user_password': request.password
}
)
if r.status_code == 200:
r = r.json()
r.update({'password': request.password})
return Obj(r)
else:
return Obj({})


def get_session(secret, token) -> dict:
try:
return jwt.decode(token, secret, algorithms=['HS256'])
Expand Down
Loading

0 comments on commit bd9c0b9

Please sign in to comment.