Formatting.
This commit is contained in:
		
							parent
							
								
									18b76ebd5e
								
							
						
					
					
						commit
						9b93403a93
					
				| @ -1,9 +1,10 @@ | |||||||
| import pathlib | import pathlib | ||||||
|  | from types import SimpleNamespace | ||||||
| 
 | 
 | ||||||
| from aiohttp import web | from aiohttp import web | ||||||
| from app.app import Application as BaseApplication | from app.app import Application as BaseApplication | ||||||
|  | 
 | ||||||
| from snek.docs.app import Application as DocsApplication | from snek.docs.app import Application as DocsApplication | ||||||
| from app.cache import time_cache_async |  | ||||||
| from snek.mapper import get_mappers | from snek.mapper import get_mappers | ||||||
| from snek.service import get_services | from snek.service import get_services | ||||||
| from snek.system import http | from snek.system import http | ||||||
| @ -17,7 +18,6 @@ from snek.view.login_form import LoginFormView | |||||||
| from snek.view.register import RegisterView | from snek.view.register import RegisterView | ||||||
| from snek.view.register_form import RegisterFormView | from snek.view.register_form import RegisterFormView | ||||||
| from snek.view.web import WebView | from snek.view.web import WebView | ||||||
| from types import SimpleNamespace |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Application(BaseApplication): | class Application(BaseApplication): | ||||||
| @ -60,7 +60,10 @@ class Application(BaseApplication): | |||||||
|         self.router.add_get("/http-get", self.handle_http_get) |         self.router.add_get("/http-get", self.handle_http_get) | ||||||
|         self.router.add_get("/http-photo", self.handle_http_photo) |         self.router.add_get("/http-photo", self.handle_http_photo) | ||||||
| 
 | 
 | ||||||
|         self.add_subapp("/docs", DocsApplication(path=pathlib.Path(__file__).parent.joinpath("docs"))) |         self.add_subapp( | ||||||
|  |             "/docs", | ||||||
|  |             DocsApplication(path=pathlib.Path(__file__).parent.joinpath("docs")), | ||||||
|  |         ) | ||||||
| 
 | 
 | ||||||
|     async def handle_test(self, request): |     async def handle_test(self, request): | ||||||
| 
 | 
 | ||||||
| @ -80,8 +83,7 @@ class Application(BaseApplication): | |||||||
|             body=path.read_bytes(), headers={"Content-Type": "image/png"} |             body=path.read_bytes(), headers={"Content-Type": "image/png"} | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|      |     # @time_cache_async(60) | ||||||
|     #@time_cache_async(60) |  | ||||||
|     async def render_template(self, template, request, context=None): |     async def render_template(self, template, request, context=None): | ||||||
|         return await super().render_template(template, request, context) |         return await super().render_template(template, request, context) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,4 +1,5 @@ | |||||||
| from snek.system.form import Form, HTMLElement,FormInputElement,FormButtonElement | from snek.system.form import Form, FormButtonElement, FormInputElement, HTMLElement | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class LoginForm(Form): | class LoginForm(Form): | ||||||
| 
 | 
 | ||||||
| @ -11,14 +12,16 @@ class LoginForm(Form): | |||||||
|         max_length=20, |         max_length=20, | ||||||
|         regex=r"^[a-zA-Z0-9_]+$", |         regex=r"^[a-zA-Z0-9_]+$", | ||||||
|         place_holder="Username", |         place_holder="Username", | ||||||
|         type="text" |         type="text", | ||||||
|  |     ) | ||||||
|  |     password = FormInputElement( | ||||||
|  |         name="password", | ||||||
|  |         required=True, | ||||||
|  |         regex=r"^[a-zA-Z0-9_.+-]{6,}", | ||||||
|  |         type="password", | ||||||
|  |         place_holder="Password", | ||||||
|     ) |     ) | ||||||
|     password = FormInputElement(name="password",required=True,regex=r"^[a-zA-Z0-9_.+-]{6,}",type="password",place_holder="Password") |  | ||||||
| 
 | 
 | ||||||
|     action = FormButtonElement( |     action = FormButtonElement( | ||||||
|         name="action", |         name="action", value="submit", text="Login", type="button" | ||||||
|         value="submit", |  | ||||||
|         text="Login", |  | ||||||
|         type="button" |  | ||||||
|     ) |     ) | ||||||
|     |  | ||||||
|  | |||||||
| @ -1,4 +1,5 @@ | |||||||
| from snek.system.form import Form, HTMLElement,FormInputElement,FormButtonElement | from snek.system.form import Form, FormButtonElement, FormInputElement, HTMLElement | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class UsernameField(FormInputElement): | class UsernameField(FormInputElement): | ||||||
| 
 | 
 | ||||||
| @ -9,6 +10,7 @@ class UsernameField(FormInputElement): | |||||||
|             result.append("Username is not available.") |             result.append("Username is not available.") | ||||||
|         return result |         return result | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class RegisterForm(Form): | class RegisterForm(Form): | ||||||
| 
 | 
 | ||||||
|     title = HTMLElement(tag="h1", text="Register") |     title = HTMLElement(tag="h1", text="Register") | ||||||
| @ -20,21 +22,23 @@ class RegisterForm(Form): | |||||||
|         max_length=20, |         max_length=20, | ||||||
|         regex=r"^[a-zA-Z0-9_]+$", |         regex=r"^[a-zA-Z0-9_]+$", | ||||||
|         place_holder="Username", |         place_holder="Username", | ||||||
|         type="text" |         type="text", | ||||||
|     ) |     ) | ||||||
|     email = FormInputElement( |     email = FormInputElement( | ||||||
|         name="email", |         name="email", | ||||||
|         required=False, |         required=False, | ||||||
|         regex=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$", |         regex=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$", | ||||||
|         place_holder="Email address", |         place_holder="Email address", | ||||||
|         type="email" |         type="email", | ||||||
|  |     ) | ||||||
|  |     password = FormInputElement( | ||||||
|  |         name="password", | ||||||
|  |         required=True, | ||||||
|  |         regex=r"^[a-zA-Z0-9_.+-]{6,}", | ||||||
|  |         type="password", | ||||||
|  |         place_holder="Password", | ||||||
|     ) |     ) | ||||||
|     password = FormInputElement(name="password",required=True,regex=r"^[a-zA-Z0-9_.+-]{6,}",type="password",place_holder="Password") |  | ||||||
| 
 | 
 | ||||||
|     action = FormButtonElement( |     action = FormButtonElement( | ||||||
|         name="action", |         name="action", value="submit", text="Register", type="button" | ||||||
|         value="submit", |  | ||||||
|         text="Register", |  | ||||||
|         type="button" |  | ||||||
|     ) |     ) | ||||||
| 
 |  | ||||||
|  | |||||||
| @ -1,12 +1,12 @@ | |||||||
| import functools | import functools | ||||||
|  | 
 | ||||||
| from snek.mapper.user import UserMapper | from snek.mapper.user import UserMapper | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| @functools.cache | @functools.cache | ||||||
| def get_mappers(app=None): | def get_mappers(app=None): | ||||||
|     return dict( |     return {"user": UserMapper(app=app)} | ||||||
|         user=UserMapper(app=app) |  | ||||||
| 
 | 
 | ||||||
|     ) |  | ||||||
| 
 | 
 | ||||||
| def get_mapper(name, app=None): | def get_mapper(name, app=None): | ||||||
|     return get_mappers(app=app)[name] |     return get_mappers(app=app)[name] | ||||||
| @ -1,5 +1,6 @@ | |||||||
| from snek.system.mapper import BaseMapper |  | ||||||
| from snek.model.user import UserModel | from snek.model.user import UserModel | ||||||
|  | from snek.system.mapper import BaseMapper | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class UserMapper(BaseMapper): | class UserMapper(BaseMapper): | ||||||
|     table_name = "user" |     table_name = "user" | ||||||
|  | |||||||
| @ -1,12 +1,12 @@ | |||||||
| from snek.model.user import UserModel  |  | ||||||
| import functools | import functools | ||||||
| 
 | 
 | ||||||
|  | from snek.model.user import UserModel | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| @functools.cache | @functools.cache | ||||||
| def get_models(): | def get_models(): | ||||||
|     return dict( |     return {"user": UserModel} | ||||||
|         user=UserModel |  | ||||||
| 
 | 
 | ||||||
|     ) |  | ||||||
| 
 | 
 | ||||||
| def get_model(name): | def get_model(name): | ||||||
|     return get_models()[name] |     return get_models()[name] | ||||||
|  | |||||||
| @ -1,4 +1,5 @@ | |||||||
| from snek.system.model import BaseModel,ModelField | from snek.system.model import BaseModel, ModelField | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class UserModel(BaseModel): | class UserModel(BaseModel): | ||||||
| 
 | 
 | ||||||
| @ -12,8 +13,6 @@ class UserModel(BaseModel): | |||||||
|     email = ModelField( |     email = ModelField( | ||||||
|         name="email", |         name="email", | ||||||
|         required=False, |         required=False, | ||||||
|         regex=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$" |         regex=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$", | ||||||
|     ) |     ) | ||||||
|     password = ModelField(name="password",required=True,regex=r"^[a-zA-Z0-9_.+-]{6,}") |     password = ModelField(name="password", required=True, regex=r"^[a-zA-Z0-9_.+-]{6,}") | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|  | |||||||
| @ -1,12 +1,13 @@ | |||||||
| from snek.service.user import UserService  |  | ||||||
| import functools | import functools | ||||||
| 
 | 
 | ||||||
|  | from snek.service.user import UserService | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| @functools.cache | @functools.cache | ||||||
| def get_services(app): | def get_services(app): | ||||||
| 
 | 
 | ||||||
|     return dict( |     return {"user": UserService(app=app)} | ||||||
|         user = UserService(app=app) | 
 | ||||||
| 
 | 
 | ||||||
|     ) |  | ||||||
| def get_service(name, app=None): | def get_service(name, app=None): | ||||||
|     return get_services(app=app)[name] |     return get_services(app=app)[name] | ||||||
| @ -1,5 +1,6 @@ | |||||||
| from snek.system.service import BaseService  |  | ||||||
| from snek.system import security | from snek.system import security | ||||||
|  | from snek.system.service import BaseService | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class UserService(BaseService): | class UserService(BaseService): | ||||||
|     mapper_name = "user" |     mapper_name = "user" | ||||||
| @ -14,4 +15,3 @@ class UserService(BaseService): | |||||||
|         if await self.save(model): |         if await self.save(model): | ||||||
|             return model |             return model | ||||||
|         raise Exception(f"Failed to create user: {model.errors}.") |         raise Exception(f"Failed to create user: {model.errors}.") | ||||||
|          |  | ||||||
| @ -1,8 +1,8 @@ | |||||||
| 
 |  | ||||||
| import functools | import functools | ||||||
| 
 | 
 | ||||||
| cache = functools.cache | cache = functools.cache | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| def async_cache(func): | def async_cache(func): | ||||||
|     cache = {} |     cache = {} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -26,8 +26,19 @@ | |||||||
| 
 | 
 | ||||||
| from snek.system import model | from snek.system import model | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class HTMLElement(model.ModelField): | class HTMLElement(model.ModelField): | ||||||
|     def __init__(self, id=None, tag="div", name=None, html=None, class_name=None, text=None, *args, **kwargs): |     def __init__( | ||||||
|  |         self, | ||||||
|  |         id=None, | ||||||
|  |         tag="div", | ||||||
|  |         name=None, | ||||||
|  |         html=None, | ||||||
|  |         class_name=None, | ||||||
|  |         text=None, | ||||||
|  |         *args, | ||||||
|  |         **kwargs, | ||||||
|  |     ): | ||||||
|         self.tag = tag |         self.tag = tag | ||||||
|         self.text = text |         self.text = text | ||||||
|         self.id = id |         self.id = id | ||||||
| @ -37,16 +48,18 @@ class HTMLElement(model.ModelField): | |||||||
| 
 | 
 | ||||||
|     async def to_json(self): |     async def to_json(self): | ||||||
|         result = await super().to_json() |         result = await super().to_json() | ||||||
|         result['text'] = self.text |         result["text"] = self.text | ||||||
|         result['id'] = self.id |         result["id"] = self.id | ||||||
|         result['html'] = self.html |         result["html"] = self.html | ||||||
|         result['class_name'] = self.class_name |         result["class_name"] = self.class_name | ||||||
|         result['tag'] = self.tag |         result["tag"] = self.tag | ||||||
|         return result |         return result | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class FormElement(HTMLElement): | class FormElement(HTMLElement): | ||||||
|     pass |     pass | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class FormInputElement(FormElement): | class FormInputElement(FormElement): | ||||||
|     def __init__(self, type="text", place_holder=None, *args, **kwargs): |     def __init__(self, type="text", place_holder=None, *args, **kwargs): | ||||||
|         super().__init__(tag="input", *args, **kwargs) |         super().__init__(tag="input", *args, **kwargs) | ||||||
| @ -59,23 +72,25 @@ class FormInputElement(FormElement): | |||||||
|         data["type"] = self.type |         data["type"] = self.type | ||||||
|         return data |         return data | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class FormButtonElement(FormElement): | class FormButtonElement(FormElement): | ||||||
|     def __init__(self, tag="button", *args, **kwargs): |     def __init__(self, tag="button", *args, **kwargs): | ||||||
|         super().__init__(tag=tag, *args, **kwargs) |         super().__init__(tag=tag, *args, **kwargs) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class Form(model.BaseModel): | class Form(model.BaseModel): | ||||||
|     @property |     @property | ||||||
|     def html_elements(self): |     def html_elements(self): | ||||||
|         return [element for element in self.fields if isinstance(element, HTMLElement)] |         return [element for element in self.fields if isinstance(element, HTMLElement)] | ||||||
| 
 | 
 | ||||||
|     def set_user_data(self, data): |     def set_user_data(self, data): | ||||||
|         return super().set_user_data(data.get('fields')) |         return super().set_user_data(data.get("fields")) | ||||||
| 
 | 
 | ||||||
|     async def to_json(self, encode=False): |     async def to_json(self, encode=False): | ||||||
|         elements = await super().to_json() |         elements = await super().to_json() | ||||||
|         html_elements = {} |         html_elements = {} | ||||||
|         for element in elements.keys(): |         for element in elements.keys(): | ||||||
|             if element == 'is_valid': |             if element == "is_valid": | ||||||
|                 # is_valid is async get property so we can't do getattr on it |                 # is_valid is async get property so we can't do getattr on it | ||||||
|                 continue |                 continue | ||||||
|             field = getattr(self, element) |             field = getattr(self, element) | ||||||
| @ -85,8 +100,12 @@ class Form(model.BaseModel): | |||||||
|                 except KeyError: |                 except KeyError: | ||||||
|                     pass |                     pass | ||||||
| 
 | 
 | ||||||
|         is_valid = all(field['is_valid'] for field in html_elements.values()) |         is_valid = all(field["is_valid"] for field in html_elements.values()) | ||||||
|         return dict(fields=html_elements, is_valid=is_valid, errors=await self.errors) |         return { | ||||||
|  |             "fields": html_elements, | ||||||
|  |             "is_valid": is_valid, | ||||||
|  |             "errors": await self.errors, | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     @property |     @property | ||||||
|     async def errors(self): |     async def errors(self): | ||||||
|  | |||||||
| @ -24,17 +24,17 @@ | |||||||
| # SOFTWARE. | # SOFTWARE. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| from aiohttp import web | import asyncio | ||||||
| import aiohttp |  | ||||||
| from app.cache import time_cache_async |  | ||||||
| from bs4 import BeautifulSoup |  | ||||||
| from urllib.parse import urljoin |  | ||||||
| import pathlib | import pathlib | ||||||
| import uuid | import uuid | ||||||
| import imgkit |  | ||||||
| import asyncio |  | ||||||
| import zlib | import zlib | ||||||
| import io | from urllib.parse import urljoin | ||||||
|  | 
 | ||||||
|  | import aiohttp | ||||||
|  | import imgkit | ||||||
|  | from app.cache import time_cache_async | ||||||
|  | from bs4 import BeautifulSoup | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| async def crc32(data): | async def crc32(data): | ||||||
|     try: |     try: | ||||||
| @ -43,6 +43,7 @@ async def crc32(data): | |||||||
|         pass |         pass | ||||||
|     return "crc32" + str(zlib.crc32(data)) |     return "crc32" + str(zlib.crc32(data)) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| async def get_file(name, suffix=".cache"): | async def get_file(name, suffix=".cache"): | ||||||
|     name = await crc32(name) |     name = await crc32(name) | ||||||
|     path = pathlib.Path(".").joinpath("cache") |     path = pathlib.Path(".").joinpath("cache") | ||||||
| @ -50,11 +51,13 @@ async def get_file(name, suffix=".cache"): | |||||||
|         path.mkdir(parents=True, exist_ok=True) |         path.mkdir(parents=True, exist_ok=True) | ||||||
|     return path.joinpath(name + suffix) |     return path.joinpath(name + suffix) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| async def public_touch(name=None): | async def public_touch(name=None): | ||||||
|     path = pathlib.Path(".").joinpath(str(uuid.uuid4()) + name) |     path = pathlib.Path(".").joinpath(str(uuid.uuid4()) + name) | ||||||
|     path.open("wb").close() |     path.open("wb").close() | ||||||
|     return path |     return path | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| async def create_site_photo(url): | async def create_site_photo(url): | ||||||
|     loop = asyncio.get_event_loop() |     loop = asyncio.get_event_loop() | ||||||
|     if not url.startswith("https"): |     if not url.startswith("https"): | ||||||
| @ -71,21 +74,23 @@ async def create_site_photo(url): | |||||||
| 
 | 
 | ||||||
|     return await loop.run_in_executor(None, make_photo) |     return await loop.run_in_executor(None, make_photo) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| async def repair_links(base_url, html_content): | async def repair_links(base_url, html_content): | ||||||
|     soup = BeautifulSoup(html_content, "html.parser") |     soup = BeautifulSoup(html_content, "html.parser") | ||||||
|     for tag in soup.find_all(['a', 'img', 'link']): |     for tag in soup.find_all(["a", "img", "link"]): | ||||||
|         if tag.has_attr('href') and not tag['href'].startswith("http"): |         if tag.has_attr("href") and not tag["href"].startswith("http"): | ||||||
|             tag['href'] = urljoin(base_url, tag['href']) |             tag["href"] = urljoin(base_url, tag["href"]) | ||||||
|         if tag.has_attr('src') and not tag['src'].startswith("http"): |         if tag.has_attr("src") and not tag["src"].startswith("http"): | ||||||
|             tag['src'] = urljoin(base_url, tag['src']) |             tag["src"] = urljoin(base_url, tag["src"]) | ||||||
|     return soup.prettify() |     return soup.prettify() | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| async def is_html_content(content: bytes): | async def is_html_content(content: bytes): | ||||||
|     try: |     try: | ||||||
|         content = content.decode(errors='ignore') |         content = content.decode(errors="ignore") | ||||||
|     except: |     except: | ||||||
|         pass |         pass | ||||||
|     marks = ['<html', '<img', '<p', '<span', '<div'] |     marks = ["<html", "<img", "<p", "<span", "<div"] | ||||||
|     try: |     try: | ||||||
|         content = content.lower() |         content = content.lower() | ||||||
|         for mark in marks: |         for mark in marks: | ||||||
| @ -95,6 +100,7 @@ async def is_html_content(content: bytes): | |||||||
|         print(ex) |         print(ex) | ||||||
|     return False |     return False | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| @time_cache_async(120) | @time_cache_async(120) | ||||||
| async def get(url): | async def get(url): | ||||||
|     async with aiohttp.ClientSession() as session: |     async with aiohttp.ClientSession() as session: | ||||||
|  | |||||||
| @ -1,15 +1,14 @@ | |||||||
| 
 |  | ||||||
| DEFAULT_LIMIT = 30 | DEFAULT_LIMIT = 30 | ||||||
| import typing | import typing | ||||||
|  | 
 | ||||||
| from snek.system.model import BaseModel | from snek.system.model import BaseModel | ||||||
| 
 | 
 | ||||||
| import types |  | ||||||
| 
 | 
 | ||||||
| class BaseMapper: | class BaseMapper: | ||||||
| 
 | 
 | ||||||
|     model_class:BaseModel = None  |     model_class: BaseModel = None | ||||||
|     default_limit:int = DEFAULT_LIMIT |     default_limit: int = DEFAULT_LIMIT | ||||||
|     table_name:str = None  |     table_name: str = None | ||||||
| 
 | 
 | ||||||
|     def __init__(self, app): |     def __init__(self, app): | ||||||
|         self.app = app |         self.app = app | ||||||
| @ -27,12 +26,12 @@ class BaseMapper: | |||||||
|     def table(self): |     def table(self): | ||||||
|         return self.db[self.table_name] |         return self.db[self.table_name] | ||||||
| 
 | 
 | ||||||
|     async def get(self, uid:str=None, **kwargs) -> BaseModel: |     async def get(self, uid: str = None, **kwargs) -> BaseModel: | ||||||
|         if uid: |         if uid: | ||||||
|             kwargs['uid'] = uid  |             kwargs["uid"] = uid | ||||||
|         model = self.new() |         self.new() | ||||||
|         record = self.table.find_one(**kwargs) |         record = self.table.find_one(**kwargs) | ||||||
|         return await self.model_class.from_record(mapper=self,record=record) |         return await self.model_class.from_record(mapper=self, record=record) | ||||||
| 
 | 
 | ||||||
|     async def exists(self, **kwargs): |     async def exists(self, **kwargs): | ||||||
|         return self.table.exists(**kwargs) |         return self.table.exists(**kwargs) | ||||||
| @ -40,19 +39,19 @@ class BaseMapper: | |||||||
|     async def count(self, **kwargs) -> int: |     async def count(self, **kwargs) -> int: | ||||||
|         return self.table.count(**kwargs) |         return self.table.count(**kwargs) | ||||||
| 
 | 
 | ||||||
|     async def save(self, model:BaseModel) -> bool: |     async def save(self, model: BaseModel) -> bool: | ||||||
|         record = await model.record |         record = await model.record | ||||||
|         if not record.get('uid'): |         if not record.get("uid"): | ||||||
|             raise Exception(f"Attempt to save without uid: {record}.") |             raise Exception(f"Attempt to save without uid: {record}.") | ||||||
|         return self.table.upsert(record,['uid']) |         return self.table.upsert(record, ["uid"]) | ||||||
| 
 | 
 | ||||||
|     async def find(self, **kwargs) -> typing.AsyncGenerator: |     async def find(self, **kwargs) -> typing.AsyncGenerator: | ||||||
|         if not kwargs.get("_limit"): |         if not kwargs.get("_limit"): | ||||||
|             kwargs["_limit"] = self.default_limit |             kwargs["_limit"] = self.default_limit | ||||||
|         for record in self.table.find(**kwargs): |         for record in self.table.find(**kwargs): | ||||||
|             yield await self.model_class.from_record(mapper=self,record=record) |             yield await self.model_class.from_record(mapper=self, record=record) | ||||||
| 
 | 
 | ||||||
|     async def delete(self, kwargs=None)-> int:  |     async def delete(self, kwargs=None) -> int: | ||||||
|         if not kwargs or not isinstance(kwargs, dict): |         if not kwargs or not isinstance(kwargs, dict): | ||||||
|             raise Exception("Can't execute delete with no filter.") |             raise Exception("Can't execute delete with no filter.") | ||||||
|         return self.table.delete(**kwargs) |         return self.table.delete(**kwargs) | ||||||
|  | |||||||
| @ -1,62 +1,65 @@ | |||||||
| 
 |  | ||||||
| # Original source: https://brandonjay.dev/posts/2021/render-markdown-html-in-python-with-jinja2 | # Original source: https://brandonjay.dev/posts/2021/render-markdown-html-in-python-with-jinja2 | ||||||
| 
 | 
 | ||||||
| from types import SimpleNamespace | from types import SimpleNamespace | ||||||
| from mistune import escape | 
 | ||||||
| from mistune import Markdown |  | ||||||
| from mistune import HTMLRenderer |  | ||||||
| from pygments import highlight |  | ||||||
| from pygments.lexers import get_lexer_by_name |  | ||||||
| from pygments.formatters import html |  | ||||||
| from pygments.styles import get_style_by_name |  | ||||||
| import functools |  | ||||||
| from app.cache import time_cache_async | from app.cache import time_cache_async | ||||||
|  | from mistune import HTMLRenderer, Markdown | ||||||
|  | from pygments import highlight | ||||||
|  | from pygments.formatters import html | ||||||
|  | from pygments.lexers import get_lexer_by_name | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class MarkdownRenderer(HTMLRenderer): | class MarkdownRenderer(HTMLRenderer): | ||||||
| 
 | 
 | ||||||
|     _allow_harmful_protocols = True |     _allow_harmful_protocols = True | ||||||
|  | 
 | ||||||
|     def __init__(self, app, template): |     def __init__(self, app, template): | ||||||
|         self.template = template |         self.template = template | ||||||
| 
 | 
 | ||||||
|         self.app = app |         self.app = app | ||||||
|         self.env = self.app.jinja2_env |         self.env = self.app.jinja2_env | ||||||
|         formatter = html.HtmlFormatter() |         formatter = html.HtmlFormatter() | ||||||
|          self.env.globals['highlight_styles'] = formatter.get_style_defs() |         self.env.globals["highlight_styles"] = formatter.get_style_defs() | ||||||
|     def _escape(self,str): | 
 | ||||||
|  |     def _escape(self, str): | ||||||
|         return str  ##escape(str) |         return str  ##escape(str) | ||||||
|     def block_code(self, code, lang=None,info=None): | 
 | ||||||
|  |     def block_code(self, code, lang=None, info=None): | ||||||
|         if not lang: |         if not lang: | ||||||
|             lang = info |             lang = info | ||||||
|         if not lang: |         if not lang: | ||||||
|             return f"<div>{code}</div>" |             return f"<div>{code}</div>" | ||||||
|             #return '\n<pre><code>%s</code></pre>\n' % escape(code) |             # return '\n<pre><code>%s</code></pre>\n' % escape(code) | ||||||
|         lexer = get_lexer_by_name(lang, stripall=True) |         lexer = get_lexer_by_name(lang, stripall=True) | ||||||
|         formatter = html.HtmlFormatter(lineseparator="<br>") |         formatter = html.HtmlFormatter(lineseparator="<br>") | ||||||
|         return highlight(code, lexer, formatter) |         return highlight(code, lexer, formatter) | ||||||
|  | 
 | ||||||
|     def render(self): |     def render(self): | ||||||
|         markdown_string = self.app.template_path.joinpath(self.template).read_text() |         markdown_string = self.app.template_path.joinpath(self.template).read_text() | ||||||
|         renderer = MarkdownRenderer(self.app,self.template) |         renderer = MarkdownRenderer(self.app, self.template) | ||||||
|         markdown = Markdown(renderer=renderer) |         markdown = Markdown(renderer=renderer) | ||||||
|         return markdown(markdown_string) |         return markdown(markdown_string) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| def render_markdown_sync(app, markdown_string): | def render_markdown_sync(app, markdown_string): | ||||||
|     renderer = MarkdownRenderer(app,None) |     renderer = MarkdownRenderer(app, None) | ||||||
|     markdown = Markdown(renderer=renderer) |     markdown = Markdown(renderer=renderer) | ||||||
|     return markdown(markdown_string) |     return markdown(markdown_string) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| @time_cache_async(120) | @time_cache_async(120) | ||||||
| async def render_markdown(app, markdown_string): | async def render_markdown(app, markdown_string): | ||||||
|      return render_markdown_sync(app,markdown_string) |     return render_markdown_sync(app, markdown_string) | ||||||
| 
 | 
 | ||||||
| from jinja2 import nodes, TemplateSyntaxError | 
 | ||||||
|  | from jinja2 import TemplateSyntaxError, nodes | ||||||
| from jinja2.ext import Extension | from jinja2.ext import Extension | ||||||
| from jinja2.nodes import Const | from jinja2.nodes import Const | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| # Source: https://ron.sh/how-to-write-a-jinja2-extension/ | # Source: https://ron.sh/how-to-write-a-jinja2-extension/ | ||||||
| class MarkdownExtension(Extension): | class MarkdownExtension(Extension): | ||||||
|     tags = {'markdown'} |     tags = {"markdown"} | ||||||
| 
 | 
 | ||||||
|     def __init__(self, environment): |     def __init__(self, environment): | ||||||
|         self.app = SimpleNamespace(jinja2_env=environment) |         self.app = SimpleNamespace(jinja2_env=environment) | ||||||
| @ -64,13 +67,15 @@ class MarkdownExtension(Extension): | |||||||
| 
 | 
 | ||||||
|     def parse(self, parser): |     def parse(self, parser): | ||||||
|         line_number = next(parser.stream).lineno |         line_number = next(parser.stream).lineno | ||||||
|         md_file = [Const('')] |         md_file = [Const("")] | ||||||
|         body = '' |         body = "" | ||||||
|         try: |         try: | ||||||
|             md_file = [parser.parse_expression()] |             md_file = [parser.parse_expression()] | ||||||
|         except TemplateSyntaxError: |         except TemplateSyntaxError: | ||||||
|             body = parser.parse_statements(['name:endmarkdown'], drop_needle=True) |             body = parser.parse_statements(["name:endmarkdown"], drop_needle=True) | ||||||
|         return nodes.CallBlock(self.call_method('_to_html', md_file), [], [], body).set_lineno(line_number) |         return nodes.CallBlock( | ||||||
|  |             self.call_method("_to_html", md_file), [], [], body | ||||||
|  |         ).set_lineno(line_number) | ||||||
| 
 | 
 | ||||||
|     def _to_html(self, md_file, caller): |     def _to_html(self, md_file, caller): | ||||||
|         return render_markdown_sync(self.app,caller()) |         return render_markdown_sync(self.app, caller()) | ||||||
|  | |||||||
| @ -8,12 +8,14 @@ | |||||||
| 
 | 
 | ||||||
| from aiohttp import web | from aiohttp import web | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| @web.middleware | @web.middleware | ||||||
| async def no_cors_middleware(request, handler): | async def no_cors_middleware(request, handler): | ||||||
|     response = await handler(request) |     response = await handler(request) | ||||||
|     response.headers.pop("Access-Control-Allow-Origin", None) |     response.headers.pop("Access-Control-Allow-Origin", None) | ||||||
|     return response |     return response | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| @web.middleware | @web.middleware | ||||||
| async def cors_allow_middleware(request, handler): | async def cors_allow_middleware(request, handler): | ||||||
|     response = await handler(request) |     response = await handler(request) | ||||||
| @ -22,12 +24,15 @@ async def cors_allow_middleware(request, handler): | |||||||
|     response.headers["Access-Control-Allow-Headers"] = "*" |     response.headers["Access-Control-Allow-Headers"] = "*" | ||||||
|     return response |     return response | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| @web.middleware | @web.middleware | ||||||
| async def cors_middleware(request, handler): | async def cors_middleware(request, handler): | ||||||
|     if request.method == "OPTIONS": |     if request.method == "OPTIONS": | ||||||
|         response = web.Response() |         response = web.Response() | ||||||
|         response.headers["Access-Control-Allow-Origin"] = "*" |         response.headers["Access-Control-Allow-Origin"] = "*" | ||||||
|         response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS" |         response.headers["Access-Control-Allow-Methods"] = ( | ||||||
|  |             "GET, POST, PUT, DELETE, OPTIONS" | ||||||
|  |         ) | ||||||
|         response.headers["Access-Control-Allow-Headers"] = "*" |         response.headers["Access-Control-Allow-Headers"] = "*" | ||||||
|         return response |         return response | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -25,12 +25,12 @@ | |||||||
| # SOFTWARE. | # SOFTWARE. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | import copy | ||||||
|  | import json | ||||||
| import re | import re | ||||||
| import uuid | import uuid | ||||||
| import json |  | ||||||
| from datetime import datetime, timezone |  | ||||||
| from collections import OrderedDict | from collections import OrderedDict | ||||||
| import copy | from datetime import datetime, timezone | ||||||
| 
 | 
 | ||||||
| TIMESTAMP_REGEX = r"^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{6}\+\d{2}:\d{2}$" | TIMESTAMP_REGEX = r"^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{6}\+\d{2}:\d{2}$" | ||||||
| 
 | 
 | ||||||
| @ -44,12 +44,21 @@ def add_attrs(**kwargs): | |||||||
|         for key, value in kwargs.items(): |         for key, value in kwargs.items(): | ||||||
|             setattr(func, key, value) |             setattr(func, key, value) | ||||||
|         return func |         return func | ||||||
|  | 
 | ||||||
|     return decorator |     return decorator | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def validate_attrs(required=False, min_length=None, max_length=None, regex=None, **kwargs): | def validate_attrs( | ||||||
|  |     required=False, min_length=None, max_length=None, regex=None, **kwargs | ||||||
|  | ): | ||||||
|     def decorator(func): |     def decorator(func): | ||||||
|         return add_attrs(required=required, min_length=min_length, max_length=max_length, regex=regex, **kwargs)(func) |         return add_attrs( | ||||||
|  |             required=required, | ||||||
|  |             min_length=min_length, | ||||||
|  |             max_length=max_length, | ||||||
|  |             regex=regex, | ||||||
|  |             **kwargs, | ||||||
|  |         )(func) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Validator: | class Validator: | ||||||
| @ -70,7 +79,21 @@ class Validator: | |||||||
|     def custom_validation(self): |     def custom_validation(self): | ||||||
|         return True |         return True | ||||||
| 
 | 
 | ||||||
|     def __init__(self, required=False, min_num=None, max_num=None, min_length=None, max_length=None, regex=None, value=None, kind=None, help_text=None, app=None, model=None, **kwargs): |     def __init__( | ||||||
|  |         self, | ||||||
|  |         required=False, | ||||||
|  |         min_num=None, | ||||||
|  |         max_num=None, | ||||||
|  |         min_length=None, | ||||||
|  |         max_length=None, | ||||||
|  |         regex=None, | ||||||
|  |         value=None, | ||||||
|  |         kind=None, | ||||||
|  |         help_text=None, | ||||||
|  |         app=None, | ||||||
|  |         model=None, | ||||||
|  |         **kwargs, | ||||||
|  |     ): | ||||||
|         self.index = Validator._index |         self.index = Validator._index | ||||||
|         Validator._index += 1 |         Validator._index += 1 | ||||||
|         self.app = app |         self.app = app | ||||||
| @ -103,9 +126,13 @@ class Validator: | |||||||
|             if self.max_num is not None and self.value > self.max_num: |             if self.max_num is not None and self.value > self.max_num: | ||||||
|                 error_list.append(f"Field should be maximal {self.max_num}.") |                 error_list.append(f"Field should be maximal {self.max_num}.") | ||||||
|         if self.min_length is not None and len(self.value) < self.min_length: |         if self.min_length is not None and len(self.value) < self.min_length: | ||||||
|             error_list.append(f"Field should be minimal {self.min_length} characters long.") |             error_list.append( | ||||||
|  |                 f"Field should be minimal {self.min_length} characters long." | ||||||
|  |             ) | ||||||
|         if self.max_length is not None and len(self.value) > self.max_length: |         if self.max_length is not None and len(self.value) > self.max_length: | ||||||
|             error_list.append(f"Field should be maximal {self.max_length} characters long.") |             error_list.append( | ||||||
|  |                 f"Field should be maximal {self.max_length} characters long." | ||||||
|  |             ) | ||||||
|         if self.regex and self.value and not re.match(self.regex, self.value): |         if self.regex and self.value and not re.match(self.regex, self.value): | ||||||
|             error_list.append("Invalid value.") |             error_list.append("Invalid value.") | ||||||
|         if self.kind and not isinstance(self.value, self.kind): |         if self.kind and not isinstance(self.value, self.kind): | ||||||
| @ -141,7 +168,7 @@ class Validator: | |||||||
|             "help_text": self.help_text, |             "help_text": self.help_text, | ||||||
|             "errors": errors, |             "errors": errors, | ||||||
|             "is_valid": is_valid, |             "is_valid": is_valid, | ||||||
|             "index": self.index |             "index": self.index, | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -156,7 +183,7 @@ class ModelField(Validator): | |||||||
| 
 | 
 | ||||||
|     async def to_json(self): |     async def to_json(self): | ||||||
|         result = await super().to_json() |         result = await super().to_json() | ||||||
|         result['name'] = self.name |         result["name"] = self.name | ||||||
|         return result |         return result | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -193,9 +220,18 @@ class UUIDField(ModelField): | |||||||
| class BaseModel: | class BaseModel: | ||||||
| 
 | 
 | ||||||
|     uid = UUIDField(name="uid", required=True) |     uid = UUIDField(name="uid", required=True) | ||||||
|     created_at = CreatedField(name="created_at", required=True, regex=TIMESTAMP_REGEX, place_holder="Created at") |     created_at = CreatedField( | ||||||
|     updated_at = UpdatedField(name="updated_at", regex=TIMESTAMP_REGEX, place_holder="Updated at") |         name="created_at", | ||||||
|     deleted_at = DeletedField(name="deleted_at", regex=TIMESTAMP_REGEX, place_holder="Deleted at") |         required=True, | ||||||
|  |         regex=TIMESTAMP_REGEX, | ||||||
|  |         place_holder="Created at", | ||||||
|  |     ) | ||||||
|  |     updated_at = UpdatedField( | ||||||
|  |         name="updated_at", regex=TIMESTAMP_REGEX, place_holder="Updated at" | ||||||
|  |     ) | ||||||
|  |     deleted_at = DeletedField( | ||||||
|  |         name="deleted_at", regex=TIMESTAMP_REGEX, place_holder="Deleted at" | ||||||
|  |     ) | ||||||
| 
 | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     async def from_record(cls, record, mapper): |     async def from_record(cls, record, mapper): | ||||||
| @ -233,10 +269,12 @@ class BaseModel: | |||||||
| 
 | 
 | ||||||
|             if isinstance(obj, Validator): |             if isinstance(obj, Validator): | ||||||
|                 self.__dict__[key] = copy.deepcopy(obj) |                 self.__dict__[key] = copy.deepcopy(obj) | ||||||
|                 self.__dict__[key].value = kwargs.pop(key, self.__dict__[key].initial_value) |                 self.__dict__[key].value = kwargs.pop( | ||||||
|  |                     key, self.__dict__[key].initial_value | ||||||
|  |                 ) | ||||||
|                 self.fields[key] = self.__dict__[key] |                 self.fields[key] = self.__dict__[key] | ||||||
|                 self.fields[key].model = self |                 self.fields[key].model = self | ||||||
|                 self.fields[key].app = kwargs.get('app') |                 self.fields[key].app = kwargs.get("app") | ||||||
| 
 | 
 | ||||||
|     def __setitem__(self, key, value): |     def __setitem__(self, key, value): | ||||||
|         obj = self.__dict__.get(key) |         obj = self.__dict__.get(key) | ||||||
| @ -254,17 +292,14 @@ class BaseModel: | |||||||
|             field = self.fields.get(key) |             field = self.fields.get(key) | ||||||
|             if not field: |             if not field: | ||||||
|                 continue |                 continue | ||||||
|             if value.get('name'): |             if value.get("name"): | ||||||
|                 value = value.get('value') |                 value = value.get("value") | ||||||
|             field.value = value |             field.value = value | ||||||
| 
 | 
 | ||||||
|      |  | ||||||
| 
 |  | ||||||
|     @property |     @property | ||||||
|     async def is_valid(self): |     async def is_valid(self): | ||||||
|         return all([await field.is_valid for field in self.fields.values()]) |         return all([await field.is_valid for field in self.fields.values()]) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     def __getitem__(self, key): |     def __getitem__(self, key): | ||||||
|         obj = self.__dict__.get(key) |         obj = self.__dict__.get(key) | ||||||
|         if isinstance(obj, Validator): |         if isinstance(obj, Validator): | ||||||
| @ -282,20 +317,22 @@ class BaseModel: | |||||||
|         obj = await self.to_json() |         obj = await self.to_json() | ||||||
|         record = {} |         record = {} | ||||||
|         for key, value in obj.items(): |         for key, value in obj.items(): | ||||||
|             if not isinstance(value, dict) or not 'value' in value: |             if not isinstance(value, dict) or "value" not in value: | ||||||
|                 continue |                 continue | ||||||
|             if getattr(self, key).save: |             if getattr(self, key).save: | ||||||
|                 record[key] = value.get('value') |                 record[key] = value.get("value") | ||||||
|         return record |         return record | ||||||
| 
 | 
 | ||||||
|     async def to_json(self, encode=False): |     async def to_json(self, encode=False): | ||||||
|         model_data = OrderedDict({ |         model_data = OrderedDict( | ||||||
|  |             { | ||||||
|                 "uid": self.uid.value, |                 "uid": self.uid.value, | ||||||
|                 "created_at": self.created_at.value, |                 "created_at": self.created_at.value, | ||||||
|                 "updated_at": self.updated_at.value, |                 "updated_at": self.updated_at.value, | ||||||
|                 "deleted_at": self.deleted_at.value, |                 "deleted_at": self.deleted_at.value, | ||||||
|             "is_valid": await self.is_valid |                 "is_valid": await self.is_valid, | ||||||
|         }) |             } | ||||||
|  |         ) | ||||||
| 
 | 
 | ||||||
|         for key, value in self.fields.items(): |         for key, value in self.fields.items(): | ||||||
|             if key == "record": |             if key == "record": | ||||||
|  | |||||||
| @ -2,7 +2,8 @@ import hashlib | |||||||
| 
 | 
 | ||||||
| DEFAULT_SALT = b"snekker-de-snek-" | DEFAULT_SALT = b"snekker-de-snek-" | ||||||
| 
 | 
 | ||||||
| async def hash(data,salt=DEFAULT_SALT): | 
 | ||||||
|  | async def hash(data, salt=DEFAULT_SALT): | ||||||
|     try: |     try: | ||||||
|         data = data.encode(errors="ignore") |         data = data.encode(errors="ignore") | ||||||
|     except AttributeError: |     except AttributeError: | ||||||
| @ -16,5 +17,6 @@ async def hash(data,salt=DEFAULT_SALT): | |||||||
|     obj = hashlib.sha256(salted) |     obj = hashlib.sha256(salted) | ||||||
|     return obj.hexdigest() |     return obj.hexdigest() | ||||||
| 
 | 
 | ||||||
| async def verify(string:str, hashed:str): | 
 | ||||||
|  | async def verify(string: str, hashed: str): | ||||||
|     return await hash(string) == hashed |     return await hash(string) == hashed | ||||||
|  | |||||||
| @ -1,13 +1,11 @@ | |||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| from snek.mapper import get_mapper | from snek.mapper import get_mapper | ||||||
| from snek.system.mapper import BaseMapper  |  | ||||||
| from snek.model.user import UserModel | from snek.model.user import UserModel | ||||||
|  | from snek.system.mapper import BaseMapper | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class BaseService: | class BaseService: | ||||||
| 
 | 
 | ||||||
|     mapper_name:BaseMapper = None |     mapper_name: BaseMapper = None | ||||||
| 
 | 
 | ||||||
|     def __init__(self, app): |     def __init__(self, app): | ||||||
|         self.app = app |         self.app = app | ||||||
| @ -28,11 +26,10 @@ class BaseService: | |||||||
|     async def get(self, **kwargs): |     async def get(self, **kwargs): | ||||||
|         return await self.mapper.get(**kwargs) |         return await self.mapper.get(**kwargs) | ||||||
| 
 | 
 | ||||||
|     async def save(self, model:UserModel): |     async def save(self, model: UserModel): | ||||||
|         # if model.is_valid: You Know why not |         # if model.is_valid: You Know why not | ||||||
|         return await self.mapper.save(model) and True |         return await self.mapper.save(model) and True | ||||||
| 
 | 
 | ||||||
|      |  | ||||||
|     async def find(self, **kwargs): |     async def find(self, **kwargs): | ||||||
|         return await self.mapper.find(**kwargs) |         return await self.mapper.find(**kwargs) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ from aiohttp import web | |||||||
| 
 | 
 | ||||||
| from snek.system.markdown import render_markdown | from snek.system.markdown import render_markdown | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class BaseView(web.View): | class BaseView(web.View): | ||||||
| 
 | 
 | ||||||
|     @property |     @property | ||||||
| @ -17,10 +18,15 @@ class BaseView(web.View): | |||||||
| 
 | 
 | ||||||
|     async def render_template(self, template_name, context=None): |     async def render_template(self, template_name, context=None): | ||||||
|         if template_name.endswith(".md"): |         if template_name.endswith(".md"): | ||||||
|             response = await self.request.app.render_template(template_name,self.request,context) |             response = await self.request.app.render_template( | ||||||
|  |                 template_name, self.request, context | ||||||
|  |             ) | ||||||
|             body = await render_markdown(self.app, response.body.decode()) |             body = await render_markdown(self.app, response.body.decode()) | ||||||
|             return web.Response(body=body,content_type="text/html") |             return web.Response(body=body, content_type="text/html") | ||||||
|         return await self.request.app.render_template(template_name, self.request,context) |         return await self.request.app.render_template( | ||||||
|  |             template_name, self.request, context | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class BaseFormView(BaseView): | class BaseFormView(BaseView): | ||||||
| 
 | 
 | ||||||
| @ -34,14 +40,14 @@ class BaseFormView(BaseView): | |||||||
|     async def post(self): |     async def post(self): | ||||||
|         form = self.form(app=self.app) |         form = self.form(app=self.app) | ||||||
|         post = await self.request.json() |         post = await self.request.json() | ||||||
|         form.set_user_data(post['form']) |         form.set_user_data(post["form"]) | ||||||
|         result = await form.to_json() |         result = await form.to_json() | ||||||
|         if post.get('action') == 'validate': |         if post.get("action") == "validate": | ||||||
|             # Pass |             # Pass | ||||||
|             pass |             pass | ||||||
|         if post.get('action') == 'submit' and result['is_valid']: |         if post.get("action") == "submit" and result["is_valid"]: | ||||||
|             await self.submit(form) |             await self.submit(form) | ||||||
|         return await self.json_response(result) |         return await self.json_response(result) | ||||||
| 
 | 
 | ||||||
|     async def submit(self,model=None): |     async def submit(self, model=None): | ||||||
|         print("Submit sucess") |         print("Submit sucess") | ||||||
|  | |||||||
| @ -9,8 +9,7 @@ Currently only some details about the internal API are available. | |||||||
| # of the snek.system.security module. | # of the snek.system.security module. | ||||||
| 
 | 
 | ||||||
| new_user_object = await app.service.user.register( | new_user_object = await app.service.user.register( | ||||||
|     username="retoor",  |     username="retoor", password="retoorded" | ||||||
|     password="retoorded" |  | ||||||
| ) | ) | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| @ -23,13 +22,14 @@ var1 = security.encrypt("data") | |||||||
| var2 = security.encrypt(b"data") | var2 = security.encrypt(b"data") | ||||||
| 
 | 
 | ||||||
| # Is correct: | # Is correct: | ||||||
| assert(var1 == var2) | assert var1 == var2 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ## How to create a basic HTML / Markdown view | ## How to create a basic HTML / Markdown view | ||||||
| ```python | ```python | ||||||
| from snek.system.view import BaseView | from snek.system.view import BaseView | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class IndexView(BaseView): | class IndexView(BaseView): | ||||||
| 
 | 
 | ||||||
|     async def get(self): |     async def get(self): | ||||||
| @ -40,8 +40,9 @@ class IndexView(BaseView): | |||||||
| ``` | ``` | ||||||
| ## How to create a FormView | ## How to create a FormView | ||||||
| ```python | ```python | ||||||
| from snek.system.view import BaseFormView |  | ||||||
| from snek.form.register import RegisterForm | from snek.form.register import RegisterForm | ||||||
|  | from snek.system.view import BaseFormView | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class RegisterFormView(BaseFormView): | class RegisterFormView(BaseFormView): | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,5 +1,3 @@ | |||||||
| 
 |  | ||||||
| 
 |  | ||||||
| from snek.system.view import BaseView | from snek.system.view import BaseView | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -8,6 +6,7 @@ class AboutHTMLView(BaseView): | |||||||
|     async def get(self): |     async def get(self): | ||||||
|         return await self.render_template("about.html") |         return await self.render_template("about.html") | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class AboutMDView(BaseView): | class AboutMDView(BaseView): | ||||||
| 
 | 
 | ||||||
|     async def get(self): |     async def get(self): | ||||||
|  | |||||||
| @ -1,6 +1,3 @@ | |||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| from snek.system.view import BaseView | from snek.system.view import BaseView | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -9,6 +6,7 @@ class DocsHTMLView(BaseView): | |||||||
|     async def get(self): |     async def get(self): | ||||||
|         return await self.render_template("docs.html") |         return await self.render_template("docs.html") | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class DocsMDView(BaseView): | class DocsMDView(BaseView): | ||||||
| 
 | 
 | ||||||
|     async def get(self): |     async def get(self): | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| from snek.system.view import BaseView | from snek.system.view import BaseView | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class IndexView(BaseView): | class IndexView(BaseView): | ||||||
| 
 | 
 | ||||||
|     async def get(self): |     async def get(self): | ||||||
|  | |||||||
| @ -1,13 +1,18 @@ | |||||||
| from snek.form.register import RegisterForm | from snek.form.register import RegisterForm | ||||||
| from snek.system.view import BaseView | from snek.system.view import BaseView | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class LoginView(BaseView): | class LoginView(BaseView): | ||||||
| 
 | 
 | ||||||
|     async def get(self): |     async def get(self): | ||||||
|         return await self.render_template("login.html")    #web.json_response({"form": RegisterForm().to_json()}) |         return await self.render_template( | ||||||
|  |             "login.html" | ||||||
|  |         )  # web.json_response({"form": RegisterForm().to_json()}) | ||||||
| 
 | 
 | ||||||
|     async def post(self): |     async def post(self): | ||||||
|         form = RegisterForm() |         form = RegisterForm() | ||||||
|         form.set_user_data(await self.request.post()) |         form.set_user_data(await self.request.post()) | ||||||
|         print(form.is_valid()) |         print(form.is_valid()) | ||||||
|         return await self.render_template("login.html", self.request)    #web.json_response({"form": RegisterForm().to_json()}) |         return await self.render_template( | ||||||
|  |             "login.html", self.request | ||||||
|  |         )  # web.json_response({"form": RegisterForm().to_json()}) | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| from snek.system.view import BaseFormView |  | ||||||
| from snek.form.login import LoginForm | from snek.form.login import LoginForm | ||||||
|  | from snek.system.view import BaseFormView | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class LoginFormView(BaseFormView): | class LoginFormView(BaseFormView): | ||||||
|     form = LoginForm |     form = LoginForm | ||||||
| @ -1,5 +1,6 @@ | |||||||
| from snek.system.view import BaseView | from snek.system.view import BaseView | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class RegisterView(BaseView): | class RegisterView(BaseView): | ||||||
| 
 | 
 | ||||||
|     async def get(self): |     async def get(self): | ||||||
|  | |||||||
| @ -1,9 +1,12 @@ | |||||||
| from snek.form.register import RegisterForm | from snek.form.register import RegisterForm | ||||||
| from snek.system.view import BaseFormView | from snek.system.view import BaseFormView | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class RegisterFormView(BaseFormView): | class RegisterFormView(BaseFormView): | ||||||
|     form = RegisterForm |     form = RegisterForm | ||||||
| 
 | 
 | ||||||
|     async def submit(self, form): |     async def submit(self, form): | ||||||
|         result = await self.app.services.user.register(form.email.value,form.username.value,form.password.value) |         result = await self.app.services.user.register( | ||||||
|         print("SUBMITTED:",result) |             form.email.value, form.username.value, form.password.value | ||||||
|  |         ) | ||||||
|  |         print("SUBMITTED:", result) | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| from snek.system.view import BaseView | from snek.system.view import BaseView | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class WebView(BaseView): | class WebView(BaseView): | ||||||
| 
 | 
 | ||||||
|     async def get(self): |     async def get(self): | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user