pyweber 1.2.0.dev20260423__tar.gz → 1.2.0.dev20260424__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.
- {pyweber-1.2.0.dev20260423/pyweber.egg-info → pyweber-1.2.0.dev20260424}/PKG-INFO +1 -1
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyproject.toml +1 -1
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/core/template.py +65 -63
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/element.py +2 -2
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424/pyweber.egg-info}/PKG-INFO +1 -1
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/LICENSE +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/MANIFEST.in +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/README.md +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/__init__.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/admin/index.html +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/admin/src/script.js +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/admin/src/style.css +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/cli/__init__.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/cli/commands.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/components/__init__.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/components/form.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/components/general.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/components/input.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/config/__init__.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/config/config.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/connection/__init__.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/connection/http.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/connection/reload.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/connection/selector.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/connection/session.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/connection/websocket.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/core/__init__.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/core/element.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/core/events.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/core/window.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/__init__.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/cookies.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/create_app.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/error_pages.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/field.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/field_storage.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/file.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/file_stream.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/headers.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/middleware.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/openapi.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/request.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/response.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/routes.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/run.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/strem_stats.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/task_manager.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/template_diff.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/models/ws_message.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/pyweber/__init__.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/pyweber/pyweber.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/.gitignore +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/config.toml +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/css.css +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/docs.html +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/favicon/android-chrome-192x192.png +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/favicon/android-chrome-512x512.png +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/favicon/apple-touch-icon.png +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/favicon/favicon-16x16.png +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/favicon/favicon-32x32.png +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/favicon/favicon.ico +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/favicon/pyweber.png +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/favicon/site.webmanifest +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/handlers.js +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/html.html +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/html401.html +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/html404.html +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/html500.html +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/js.js +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/loading.html +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/main.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/pyweber.css +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/update.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/utils/__init__.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/utils/exceptions.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/utils/loads.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/utils/types.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/utils/utils.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber.egg-info/SOURCES.txt +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber.egg-info/dependency_links.txt +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber.egg-info/entry_points.txt +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber.egg-info/requires.txt +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber.egg-info/top_level.txt +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/setup.cfg +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/tests/test_config.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/tests/test_cookies.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/tests/test_response.py +0 -0
- {pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/tests/test_template_diff.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pyweber"
|
|
7
|
-
version = "1.2.0.
|
|
7
|
+
version = "1.2.0.dev20260424"
|
|
8
8
|
description = "A lightweight Python framework for building and managing web applications."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "DevPythonMZ", email = "pypi.dev@gmail.com" }]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import re
|
|
2
3
|
from uuid import uuid4
|
|
3
4
|
import lxml.html as HTMLPARSER
|
|
4
5
|
from lxml.etree import Element as LXML_Element
|
|
@@ -10,6 +11,7 @@ from pyweber.utils.types import HTTPStatusCode, GetBy
|
|
|
10
11
|
|
|
11
12
|
class Template: # pragma: no cover
|
|
12
13
|
def __init__(self, template: str, status_code: int = 200, title: str = None, include_uuid: bool = True, **kwargs):
|
|
14
|
+
self.__include_uuid = include_uuid
|
|
13
15
|
self.__template = self.__read_file(file_path=template)
|
|
14
16
|
self.kwargs = kwargs
|
|
15
17
|
self.data = None
|
|
@@ -17,39 +19,38 @@ class Template: # pragma: no cover
|
|
|
17
19
|
self.__icon: str = self.get_icon()
|
|
18
20
|
self.title = title
|
|
19
21
|
self.__root = self.parse_html()
|
|
20
|
-
self.__include_uuid = include_uuid
|
|
21
22
|
|
|
22
23
|
@property
|
|
23
24
|
def template(self):
|
|
24
25
|
return self.__template
|
|
25
|
-
|
|
26
|
+
|
|
26
27
|
@property
|
|
27
28
|
def root(self):
|
|
28
29
|
return self.__root
|
|
29
|
-
|
|
30
|
+
|
|
30
31
|
@root.setter
|
|
31
32
|
def root(self, value: Element):
|
|
32
33
|
if value.tag != 'html':
|
|
33
34
|
raise ValueError('This Element is not valid to root. Please add the Html Element')
|
|
34
|
-
|
|
35
|
+
|
|
35
36
|
self.__root = value
|
|
36
|
-
|
|
37
|
+
|
|
37
38
|
@property
|
|
38
39
|
def status_code(self):
|
|
39
40
|
return self.__status_code
|
|
40
|
-
|
|
41
|
+
|
|
41
42
|
@status_code.setter
|
|
42
43
|
def status_code(self, code: int):
|
|
43
44
|
if code not in HTTPStatusCode.code_list():
|
|
44
45
|
raise ValueError(f'The code {code} is not a HttpStatusCode')
|
|
45
|
-
|
|
46
|
+
|
|
46
47
|
self.__status_code = code
|
|
47
48
|
|
|
48
49
|
@property
|
|
49
50
|
def events(self):
|
|
50
51
|
from pyweber.core.events import EventBook
|
|
51
52
|
return EventBook
|
|
52
|
-
|
|
53
|
+
|
|
53
54
|
@property
|
|
54
55
|
def title(self): return self.__title
|
|
55
56
|
|
|
@@ -62,10 +63,10 @@ class Template: # pragma: no cover
|
|
|
62
63
|
|
|
63
64
|
if title:
|
|
64
65
|
title.content = value if value else title.content
|
|
65
|
-
|
|
66
|
+
|
|
66
67
|
@property
|
|
67
68
|
def head(self): return self.root.querySelector('head')
|
|
68
|
-
|
|
69
|
+
|
|
69
70
|
@property
|
|
70
71
|
def body(self): return self.root.querySelector('body')
|
|
71
72
|
|
|
@@ -74,29 +75,29 @@ class Template: # pragma: no cover
|
|
|
74
75
|
|
|
75
76
|
def get_icon(self):
|
|
76
77
|
return str(config['app'].get('icon'))
|
|
77
|
-
|
|
78
|
+
|
|
78
79
|
def parse_html(self, html: str = None):
|
|
79
80
|
if not html:
|
|
80
81
|
html = self.__template
|
|
81
|
-
|
|
82
|
+
|
|
82
83
|
return self.__inject_default_elements(root=self.__parse_html(html=html))
|
|
83
84
|
|
|
84
85
|
def build_html(self, include_doctype: bool = True):
|
|
85
86
|
html = self.root.to_html(include_uuid=self.__include_uuid)
|
|
86
|
-
|
|
87
|
+
|
|
87
88
|
if include_doctype:
|
|
88
89
|
html = f'<!DOCTYPE html>\n{html}'
|
|
89
|
-
|
|
90
|
+
|
|
90
91
|
return html
|
|
91
|
-
|
|
92
|
+
|
|
92
93
|
def getElement(self, by: GetBy, value: str, element: Element = None):
|
|
93
94
|
if not element: element = self.root
|
|
94
95
|
return element.getElement(by=by, value=value)
|
|
95
|
-
|
|
96
|
+
|
|
96
97
|
def getElements(self, by: GetBy, value: str, element: Element = None):
|
|
97
98
|
if not element: element = self.root
|
|
98
99
|
return element.getElements(by=by, value=value)
|
|
99
|
-
|
|
100
|
+
|
|
100
101
|
def querySelector(self, selector: str, element: Element = None):
|
|
101
102
|
if element is None: element = self.__root
|
|
102
103
|
return element.querySelector(selector=selector)
|
|
@@ -104,38 +105,38 @@ class Template: # pragma: no cover
|
|
|
104
105
|
def querySelectorAll(self, selector: str, element: Element = None) -> list[Element]:
|
|
105
106
|
if element is None: element = self.__root
|
|
106
107
|
return element.querySelectorAll(selector=selector)
|
|
107
|
-
|
|
108
|
+
|
|
108
109
|
def __parse_html(self, html: str) -> Element:
|
|
109
110
|
if not html.replace('<!DOCTYPE html>', '').strip().startswith('<html'):
|
|
110
111
|
if not html.startswith('<body'):
|
|
111
112
|
html = f'<body>{html}</body>'
|
|
112
113
|
html = f'<html>{html}</html>'
|
|
113
|
-
|
|
114
|
+
|
|
114
115
|
root: HTMLPARSER.HtmlElement = HTMLPARSER.fromstring(html=html)
|
|
115
|
-
|
|
116
|
+
|
|
116
117
|
if root.find(path='head') is None:
|
|
117
118
|
root.insert(0, LXML_Element('head'))
|
|
118
|
-
|
|
119
|
+
|
|
119
120
|
return self.__create_element(HTMLElement=root)
|
|
120
|
-
|
|
121
|
+
|
|
121
122
|
def __create_element(self, HTMLElement: HTMLPARSER.HtmlElement, parent: Element = None):
|
|
122
123
|
def gettail(html_element: str | None):
|
|
123
124
|
try:
|
|
124
125
|
return html_element.strip()
|
|
125
126
|
except:
|
|
126
127
|
return html_element
|
|
127
|
-
|
|
128
|
+
|
|
128
129
|
if isinstance(HTMLElement, HTMLPARSER.HtmlComment):
|
|
129
130
|
name = 'comment'
|
|
130
131
|
else:
|
|
131
132
|
name = HTMLElement.tag
|
|
132
133
|
|
|
133
|
-
id = self.__render_dynamic_values(content=HTMLElement.attrib.pop('id', None))
|
|
134
|
+
id = self.__render_dynamic_values(content=HTMLElement.attrib.pop('id', None), include_uuid=self.__include_uuid)
|
|
134
135
|
|
|
135
|
-
class_str = self.__render_dynamic_values(content=HTMLElement.attrib.pop('class', None))
|
|
136
|
+
class_str = self.__render_dynamic_values(content=HTMLElement.attrib.pop('class', None), include_uuid=self.__include_uuid)
|
|
136
137
|
classes = class_str.split() if class_str else []
|
|
137
138
|
|
|
138
|
-
style_str: str = self.__render_dynamic_values(content=HTMLElement.attrib.pop('style', None))
|
|
139
|
+
style_str: str = self.__render_dynamic_values(content=HTMLElement.attrib.pop('style', None), include_uuid=self.__include_uuid)
|
|
139
140
|
style_dict = {}
|
|
140
141
|
|
|
141
142
|
if style_str:
|
|
@@ -148,11 +149,11 @@ class Template: # pragma: no cover
|
|
|
148
149
|
|
|
149
150
|
parent = parent
|
|
150
151
|
uuid = HTMLElement.attrib.pop('uuid', None)
|
|
151
|
-
value = self.__render_dynamic_values(content=HTMLElement.attrib.pop('value', None))
|
|
152
|
-
content: str = self.__render_dynamic_values(content=HTMLElement.text if HTMLElement.text else None)
|
|
152
|
+
value = self.__render_dynamic_values(content=HTMLElement.attrib.pop('value', None), include_uuid=self.__include_uuid)
|
|
153
|
+
content: str = self.__render_dynamic_values(content=HTMLElement.text if HTMLElement.text else None, include_uuid=self.__include_uuid)
|
|
153
154
|
events_dict = {key[1:]: HTMLElement.attrib.pop(key) for key in HTMLElement.attrib if key.startswith('_on')}
|
|
154
155
|
childrens: list[HTMLPARSER.HtmlElement] = HTMLElement.getchildren()
|
|
155
|
-
|
|
156
|
+
|
|
156
157
|
event_obj = TemplateEvents()
|
|
157
158
|
for key, event in events_dict.items():
|
|
158
159
|
if hasattr(event_obj, key):
|
|
@@ -180,69 +181,70 @@ class Template: # pragma: no cover
|
|
|
180
181
|
|
|
181
182
|
for child in childrens:
|
|
182
183
|
element.childs.append(self.__create_element(child, element))
|
|
183
|
-
|
|
184
|
+
|
|
184
185
|
return element
|
|
185
|
-
|
|
186
|
-
def __render_dynamic_values(self, content: str):
|
|
186
|
+
|
|
187
|
+
def __render_dynamic_values(self, content: str, include_uuid: bool = True):
|
|
187
188
|
if content:
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
189
|
+
pattern = r'\{\{(.*?)\}\}'
|
|
190
|
+
result = re.findall(pattern, content)
|
|
191
|
+
|
|
192
|
+
if result:
|
|
193
|
+
for r in result:
|
|
194
|
+
value = self.kwargs.get(r.strip(), None)
|
|
195
|
+
if value is not None:
|
|
196
|
+
if isinstance(value, Element):
|
|
197
|
+
value = self.to_html(element=value, include_uuid=include_uuid)
|
|
198
|
+
|
|
199
|
+
content = content.replace("{{" + r + "}}", str(value))
|
|
200
|
+
|
|
199
201
|
return content
|
|
200
202
|
|
|
201
203
|
def __read_file(self, file_path: str) -> str:
|
|
202
204
|
from pyweber.models.error_pages import ErrorPages
|
|
203
205
|
if file_path.endswith('.html'):
|
|
204
206
|
path = os.path.join('templates', file_path) if not os.path.isfile(file_path) else file_path
|
|
205
|
-
|
|
207
|
+
|
|
206
208
|
try:
|
|
207
209
|
return LoadStaticFiles(path=path).load
|
|
208
|
-
|
|
210
|
+
|
|
209
211
|
except FileNotFoundError:
|
|
210
212
|
return ErrorPages().page_server_error.build_html().replace(
|
|
211
213
|
"{{error}}",
|
|
212
214
|
f'{path} not found, please include on templates file'
|
|
213
215
|
)
|
|
214
|
-
|
|
216
|
+
|
|
215
217
|
return file_path
|
|
216
|
-
|
|
218
|
+
|
|
217
219
|
def __create_default_element(self, *args, **kwargs):
|
|
218
220
|
return Element(*args, **kwargs)
|
|
219
|
-
|
|
221
|
+
|
|
220
222
|
def __inject_default_elements(self, root: Element):
|
|
221
223
|
has_websocket_script, has_icon, has_description, has_css, has_keywords, has_title = False, False, False, False, False, False
|
|
222
224
|
for child in root.childs[0].childs:
|
|
223
225
|
if child.tag == 'script' and child.get_attr('src', '').startswith('/_pyweber/static/') and child.get_attr('src', '').endswith('/.js'):
|
|
224
226
|
has_websocket_script = True
|
|
225
|
-
|
|
227
|
+
|
|
226
228
|
elif child.tag == 'link':
|
|
227
229
|
if 'icon' in list(child.attrs.values()):
|
|
228
230
|
has_icon = True
|
|
229
|
-
|
|
231
|
+
|
|
230
232
|
elif child.get_attr('rel') == 'stylesheet' and child.get_attr('href', '').startswith('/_pyweber/static/') and child.get_attr('href', '').endswith('/.css'):
|
|
231
233
|
has_css = True
|
|
232
|
-
|
|
234
|
+
|
|
233
235
|
elif child.tag == 'meta':
|
|
234
236
|
if 'description' in list(child.attrs.values()):
|
|
235
237
|
has_description = True
|
|
236
|
-
|
|
238
|
+
|
|
237
239
|
elif 'keywords' in list(child.attrs.values()):
|
|
238
240
|
has_keywords = True
|
|
239
|
-
|
|
241
|
+
|
|
240
242
|
elif child.tag == 'title':
|
|
241
243
|
has_title = child
|
|
242
|
-
|
|
244
|
+
|
|
243
245
|
if has_websocket_script and has_icon and has_css and has_description and has_keywords and has_title:
|
|
244
246
|
break
|
|
245
|
-
|
|
247
|
+
|
|
246
248
|
if not has_websocket_script:
|
|
247
249
|
# insert websockets port if exists
|
|
248
250
|
disable_ws = os.environ.get('PYWEBER_DISABLE_WS', False)
|
|
@@ -256,7 +258,7 @@ class Template: # pragma: no cover
|
|
|
256
258
|
)
|
|
257
259
|
]
|
|
258
260
|
)
|
|
259
|
-
|
|
261
|
+
|
|
260
262
|
if not has_icon:
|
|
261
263
|
root.childs[0].childs.append(
|
|
262
264
|
self.__create_default_element(
|
|
@@ -264,7 +266,7 @@ class Template: # pragma: no cover
|
|
|
264
266
|
attrs={'rel': 'icon', 'href': f'{self.__icon.strip()}'.replace('\\', '/')}
|
|
265
267
|
)
|
|
266
268
|
)
|
|
267
|
-
|
|
269
|
+
|
|
268
270
|
if not has_css:
|
|
269
271
|
root.childs[0].childs.insert(
|
|
270
272
|
1,
|
|
@@ -273,7 +275,7 @@ class Template: # pragma: no cover
|
|
|
273
275
|
attrs={'rel': 'stylesheet', 'href': f'/_pyweber/static/{str(uuid4())}/.css'}
|
|
274
276
|
)
|
|
275
277
|
)
|
|
276
|
-
|
|
278
|
+
|
|
277
279
|
if not has_description:
|
|
278
280
|
root.childs[0].childs.insert(
|
|
279
281
|
0,
|
|
@@ -282,7 +284,7 @@ class Template: # pragma: no cover
|
|
|
282
284
|
attrs={'name': 'description', 'content': config['app'].get('description')}
|
|
283
285
|
)
|
|
284
286
|
)
|
|
285
|
-
|
|
287
|
+
|
|
286
288
|
if not has_keywords:
|
|
287
289
|
root.childs[0].childs.insert(
|
|
288
290
|
0,
|
|
@@ -291,10 +293,10 @@ class Template: # pragma: no cover
|
|
|
291
293
|
attrs={'name': 'keywords', 'content': ', '.join(config['app'].get('keywords', []))}
|
|
292
294
|
)
|
|
293
295
|
)
|
|
294
|
-
|
|
296
|
+
|
|
295
297
|
if isinstance(has_title, Element):
|
|
296
298
|
has_title.content = self.title if self.title else has_title.content
|
|
297
|
-
|
|
299
|
+
|
|
298
300
|
else:
|
|
299
301
|
root.childs[0].childs.append(
|
|
300
302
|
self.__create_default_element(
|
|
@@ -304,7 +306,7 @@ class Template: # pragma: no cover
|
|
|
304
306
|
)
|
|
305
307
|
|
|
306
308
|
return root
|
|
307
|
-
|
|
309
|
+
|
|
308
310
|
def clone(self):
|
|
309
311
|
tpl = Template(
|
|
310
312
|
template=self.template,
|
|
@@ -315,4 +317,4 @@ class Template: # pragma: no cover
|
|
|
315
317
|
tpl.data = self.data
|
|
316
318
|
tpl.root = self.root.clone
|
|
317
319
|
|
|
318
|
-
return tpl
|
|
320
|
+
return tpl
|
|
@@ -452,6 +452,7 @@ class ElementConstrutor: # pragma: no cover
|
|
|
452
452
|
|
|
453
453
|
def __render_dynamic_values(self, content: str, include_uuid: bool = True):
|
|
454
454
|
|
|
455
|
+
|
|
455
456
|
if content:
|
|
456
457
|
pattern = r'\{\{(.*?)\}\}'
|
|
457
458
|
result = re.findall(pattern, content)
|
|
@@ -459,8 +460,7 @@ class ElementConstrutor: # pragma: no cover
|
|
|
459
460
|
if result:
|
|
460
461
|
for r in result:
|
|
461
462
|
value = self.kwargs.get(r.strip(), None)
|
|
462
|
-
if value:
|
|
463
|
-
|
|
463
|
+
if value is not None:
|
|
464
464
|
if isinstance(value, ElementConstrutor):
|
|
465
465
|
value = self.to_html(element=value, include_uuid=include_uuid)
|
|
466
466
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/favicon/apple-touch-icon.png
RENAMED
|
File without changes
|
{pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/favicon/favicon-16x16.png
RENAMED
|
File without changes
|
{pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/favicon/favicon-32x32.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber/static/favicon/site.webmanifest
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyweber-1.2.0.dev20260423 → pyweber-1.2.0.dev20260424}/pyweber.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|