pyweber 1.2.0.dev20260428__tar.gz → 1.2.0.dev20260430__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.dev20260428/pyweber.egg-info → pyweber-1.2.0.dev20260430}/PKG-INFO +1 -1
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyproject.toml +1 -1
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/core/element.py +18 -15
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/core/template.py +1 -18
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/element.py +3 -4
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/template_diff.py +19 -24
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430/pyweber.egg-info}/PKG-INFO +1 -1
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/LICENSE +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/MANIFEST.in +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/README.md +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/__init__.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/admin/index.html +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/admin/src/script.js +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/admin/src/style.css +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/cli/__init__.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/cli/commands.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/components/__init__.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/components/form.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/components/general.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/components/input.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/config/__init__.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/config/config.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/connection/__init__.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/connection/http.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/connection/reload.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/connection/selector.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/connection/session.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/connection/websocket.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/core/__init__.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/core/events.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/core/window.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/__init__.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/cookies.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/create_app.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/error_pages.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/field.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/field_storage.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/file.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/file_stream.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/headers.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/middleware.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/openapi.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/request.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/response.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/routes.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/run.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/strem_stats.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/task_manager.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/models/ws_message.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/pyweber/__init__.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/pyweber/pyweber.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/.gitignore +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/config.toml +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/css.css +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/docs.html +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/favicon/android-chrome-192x192.png +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/favicon/android-chrome-512x512.png +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/favicon/apple-touch-icon.png +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/favicon/favicon-16x16.png +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/favicon/favicon-32x32.png +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/favicon/favicon.ico +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/favicon/pyweber.png +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/favicon/site.webmanifest +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/handlers.js +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/html.html +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/html401.html +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/html404.html +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/html500.html +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/js.js +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/loading.html +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/main.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/pyweber.css +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/update.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/utils/__init__.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/utils/exceptions.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/utils/loads.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/utils/types.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/utils/utils.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber.egg-info/SOURCES.txt +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber.egg-info/dependency_links.txt +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber.egg-info/entry_points.txt +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber.egg-info/requires.txt +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber.egg-info/top_level.txt +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/setup.cfg +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/tests/test_config.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/tests/test_cookies.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/tests/test_response.py +0 -0
- {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/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.dev20260430"
|
|
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,8 +1,10 @@
|
|
|
1
|
+
import os
|
|
1
2
|
import re
|
|
2
3
|
from uuid import uuid4
|
|
3
4
|
import lxml.html as HTMLPARSER
|
|
4
5
|
from lxml.html import fromstring
|
|
5
6
|
from typing import Union, Any, Literal
|
|
7
|
+
from pyweber.utils.loads import LoadStaticFiles
|
|
6
8
|
from pyweber.utils.types import HTMLTag, GetBy
|
|
7
9
|
from pyweber.models.file import File
|
|
8
10
|
from pyweber.models.element import (
|
|
@@ -244,33 +246,23 @@ class Element(ElementConstrutor): # pragma: no cover
|
|
|
244
246
|
|
|
245
247
|
def querySelector(self, selector: str, element: 'Element' = None, search_mode: SEARCH_MODE = 'exact') -> 'Element':
|
|
246
248
|
results = self.querySelectorAll(selector=selector, element=element, search_mode=search_mode)
|
|
247
|
-
|
|
248
249
|
return results[0] if results else None
|
|
249
250
|
|
|
250
251
|
def querySelectorAll(self, selector: str, element: 'Element' = None, search_mode: SEARCH_MODE = 'exact') -> list['Element']:
|
|
251
252
|
element = element or self
|
|
252
|
-
results: list['Element'] = []
|
|
253
253
|
|
|
254
254
|
if selector.startswith('.'):
|
|
255
255
|
classes = ' '.join(selector.split('.')).strip()
|
|
256
|
-
return self.getElements(by=GetBy.classes, value=classes, search_mode=search_mode)
|
|
256
|
+
return self.getElements(by=GetBy.classes, value=classes, element=element, search_mode=search_mode)
|
|
257
257
|
|
|
258
258
|
elif selector.startswith('#'):
|
|
259
|
-
|
|
260
|
-
results.append(element)
|
|
259
|
+
return self.getElements(by='id', value=selector[1:].strip(), element=element, search_mode=search_mode)
|
|
261
260
|
|
|
262
261
|
elif selector.startswith('['):
|
|
263
262
|
sel = selector.removeprefix('[').removesuffix(']')
|
|
264
|
-
return self.getElements(by=
|
|
265
|
-
|
|
266
|
-
else:
|
|
267
|
-
if selector.strip() == element.tag:
|
|
268
|
-
results.append(element)
|
|
269
|
-
|
|
270
|
-
for child in element.childs:
|
|
271
|
-
results.extend(self.querySelectorAll(selector=selector, element=child, search_mode=search_mode))
|
|
263
|
+
return self.getElements(by='attrs', value=sel, element=element, search_mode=search_mode)
|
|
272
264
|
|
|
273
|
-
return
|
|
265
|
+
return self.getElements(by='tag', value=selector.strip(), element=element, search_mode=search_mode)
|
|
274
266
|
|
|
275
267
|
@property
|
|
276
268
|
def clone(self):
|
|
@@ -339,7 +331,7 @@ class Element(ElementConstrutor): # pragma: no cover
|
|
|
339
331
|
|
|
340
332
|
@classmethod
|
|
341
333
|
def from_html(cls, html: str, include_uuid: bool = True, **kwargs):
|
|
342
|
-
HtmlElement = fromstring(html.strip())
|
|
334
|
+
HtmlElement = fromstring(cls.read_file(html).strip())
|
|
343
335
|
return cls._create_element(HTMLElement=HtmlElement, parent=None, include_uuid=include_uuid, **kwargs)
|
|
344
336
|
|
|
345
337
|
@classmethod
|
|
@@ -422,6 +414,16 @@ class Element(ElementConstrutor): # pragma: no cover
|
|
|
422
414
|
except: pass
|
|
423
415
|
return element
|
|
424
416
|
|
|
417
|
+
@classmethod
|
|
418
|
+
def read_file(cls, file_path: str) -> str:
|
|
419
|
+
if file_path.endswith('.html'):
|
|
420
|
+
path = os.path.join('templates', file_path) if not os.path.isfile(file_path) else file_path
|
|
421
|
+
|
|
422
|
+
try: return LoadStaticFiles(path=path).load
|
|
423
|
+
except FileNotFoundError: raise FileNotFoundError(f'{path} not found, please include on templates path')
|
|
424
|
+
|
|
425
|
+
return file_path
|
|
426
|
+
|
|
425
427
|
def update(self):
|
|
426
428
|
raise NotImplementedError
|
|
427
429
|
|
|
@@ -433,5 +435,6 @@ class Element(ElementConstrutor): # pragma: no cover
|
|
|
433
435
|
else:
|
|
434
436
|
return obj
|
|
435
437
|
|
|
438
|
+
|
|
436
439
|
def __str__(self):
|
|
437
440
|
return self.to_html()
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from uuid import uuid4
|
|
3
3
|
from pyweber.core.element import Element, SEARCH_MODE
|
|
4
|
-
from pyweber.utils.loads import LoadStaticFiles
|
|
5
4
|
from pyweber.config.config import config
|
|
6
5
|
from pyweber.utils.types import HTTPStatusCode, GetBy
|
|
7
6
|
|
|
8
7
|
class Template: # pragma: no cover
|
|
9
8
|
def __init__(self, template: str, status_code: int = 200, title: str = None, include_uuid: bool = True, **kwargs):
|
|
10
9
|
self.__include_uuid = include_uuid
|
|
11
|
-
self.__template =
|
|
10
|
+
self.__template = Element.read_file(file_path=template)
|
|
12
11
|
self.kwargs = kwargs
|
|
13
12
|
self.data = None
|
|
14
13
|
self.__status_code = status_code
|
|
@@ -135,22 +134,6 @@ class Template: # pragma: no cover
|
|
|
135
134
|
|
|
136
135
|
return element
|
|
137
136
|
|
|
138
|
-
def __read_file(self, file_path: str) -> str:
|
|
139
|
-
from pyweber.models.error_pages import ErrorPages
|
|
140
|
-
if file_path.endswith('.html'):
|
|
141
|
-
path = os.path.join('templates', file_path) if not os.path.isfile(file_path) else file_path
|
|
142
|
-
|
|
143
|
-
try:
|
|
144
|
-
return LoadStaticFiles(path=path).load
|
|
145
|
-
|
|
146
|
-
except FileNotFoundError:
|
|
147
|
-
return ErrorPages().page_server_error.build_html().replace(
|
|
148
|
-
"{{error}}",
|
|
149
|
-
f'{path} not found, please include on templates file'
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
return file_path
|
|
153
|
-
|
|
154
137
|
def __create_default_element(self, *args, **kwargs):
|
|
155
138
|
return Element(*args, **kwargs)
|
|
156
139
|
|
|
@@ -369,8 +369,7 @@ class ElementConstrutor: # pragma: no cover
|
|
|
369
369
|
else:
|
|
370
370
|
child.remove_attr('selected')
|
|
371
371
|
|
|
372
|
-
elif self.
|
|
373
|
-
self.__value = None
|
|
372
|
+
elif self.attrs.get('type', None) == 'checkbox':
|
|
374
373
|
if value == 'on':
|
|
375
374
|
self.set_attr('checked', '')
|
|
376
375
|
|
|
@@ -468,7 +467,7 @@ class ElementConstrutor: # pragma: no cover
|
|
|
468
467
|
return html
|
|
469
468
|
|
|
470
469
|
@classmethod
|
|
471
|
-
def render_dynamic_values(
|
|
470
|
+
def render_dynamic_values(cls, content: str, **kwargs):
|
|
472
471
|
|
|
473
472
|
if content:
|
|
474
473
|
pattern = r'\{\{(.*?)\}\}'
|
|
@@ -479,7 +478,7 @@ class ElementConstrutor: # pragma: no cover
|
|
|
479
478
|
value = kwargs.get(r.strip(), None)
|
|
480
479
|
if value is not None:
|
|
481
480
|
if isinstance(value, ElementConstrutor):
|
|
482
|
-
value =
|
|
481
|
+
value = value.to_html(element=value)
|
|
483
482
|
|
|
484
483
|
content = content.replace("{{" + r + "}}", str(value))
|
|
485
484
|
return content
|
|
@@ -6,10 +6,10 @@ class TemplateDiff: # pragma: no cover
|
|
|
6
6
|
def __init__(self):
|
|
7
7
|
self.__differences: dict[str, dict[str, str]] = {}
|
|
8
8
|
self.__checked_elements: list[Element] = []
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
@property
|
|
11
11
|
def differences(self): return self.__differences
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
def __raise_typr_error(self, *elements: Element):
|
|
14
14
|
for element in elements:
|
|
15
15
|
if not isinstance(element, Element):
|
|
@@ -18,49 +18,39 @@ class TemplateDiff: # pragma: no cover
|
|
|
18
18
|
def track_differences(self, new_element: Union[Element, Template], old_element: Union[Element, Template]):
|
|
19
19
|
if isinstance(old_element, Template):
|
|
20
20
|
old_element = old_element.root
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
if isinstance(new_element, Template):
|
|
23
23
|
new_element = new_element.root
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
self.__raise_typr_error(old_element, new_element)
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
status = None
|
|
28
28
|
methods = new_element.get_element_methods()
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
if new_element.uuid != old_element.uuid:
|
|
31
31
|
status = 'Added'
|
|
32
|
-
|
|
33
32
|
else:
|
|
34
33
|
if new_element.id != old_element.id:
|
|
35
34
|
status = 'Changed'
|
|
36
|
-
|
|
37
35
|
elif new_element.content != old_element.content:
|
|
38
36
|
status = 'Changed'
|
|
39
|
-
|
|
40
37
|
elif new_element.value != old_element.value:
|
|
41
38
|
status = 'Changed'
|
|
42
|
-
|
|
43
39
|
elif new_element.tag != old_element.tag:
|
|
44
40
|
status = 'Changed'
|
|
45
|
-
|
|
46
41
|
elif new_element.attrs != old_element.attrs:
|
|
47
42
|
status = 'Changed'
|
|
48
|
-
|
|
49
43
|
elif new_element.style != old_element.style:
|
|
50
44
|
status = 'Changed'
|
|
51
|
-
|
|
52
45
|
elif new_element.events.__dict__ != old_element.events.__dict__:
|
|
53
46
|
status = 'Changed'
|
|
54
|
-
|
|
55
47
|
elif [v for v in new_element.classes if v not in old_element.classes]:
|
|
56
48
|
status = 'Changed'
|
|
57
|
-
|
|
58
49
|
elif [v for v in old_element.classes if v not in new_element.classes]:
|
|
59
50
|
status = 'Changed'
|
|
60
|
-
|
|
61
51
|
elif methods:
|
|
62
52
|
status = 'Changed'
|
|
63
|
-
|
|
53
|
+
|
|
64
54
|
if status:
|
|
65
55
|
self.add_element_on_diff(element=new_element, status=status, methods=methods)
|
|
66
56
|
|
|
@@ -68,22 +58,27 @@ class TemplateDiff: # pragma: no cover
|
|
|
68
58
|
self.add_element_on_diff(element=old_element, status='Removed', methods=methods)
|
|
69
59
|
|
|
70
60
|
self.__checked_elements.append(new_element.uuid)
|
|
71
|
-
|
|
61
|
+
|
|
72
62
|
new_element_childs_map = {child.uuid: child for child in new_element.childs}
|
|
73
63
|
old_element_childs_map = {child.uuid: child for child in old_element.childs}
|
|
74
|
-
|
|
64
|
+
|
|
75
65
|
for uuid, old_child in old_element_childs_map.items():
|
|
76
66
|
if uuid in new_element_childs_map:
|
|
77
67
|
if old_child.parent and old_child.parent.uuid not in self.__checked_elements:
|
|
78
68
|
self.track_differences(new_element_childs_map[uuid], old_child)
|
|
79
|
-
|
|
80
69
|
else:
|
|
81
|
-
|
|
70
|
+
# ✅ só marca Removed se o pai NÃO está já no diff como Changed
|
|
71
|
+
parent_uuid = old_child.parent.uuid if old_child.parent else None
|
|
72
|
+
if parent_uuid not in self.__differences or self.__differences[parent_uuid]['status'] != 'Changed':
|
|
73
|
+
self.add_element_on_diff(element=old_child, status='Removed', methods=methods)
|
|
82
74
|
|
|
83
75
|
for uuid, new_child in new_element_childs_map.items():
|
|
84
76
|
if uuid not in old_element_childs_map:
|
|
85
|
-
|
|
86
|
-
|
|
77
|
+
# ✅ só marca Added se o pai NÃO está já no diff como Changed
|
|
78
|
+
parent_uuid = new_child.parent.uuid if new_child.parent else None
|
|
79
|
+
if parent_uuid not in self.__differences or self.__differences[parent_uuid]['status'] != 'Changed':
|
|
80
|
+
self.add_element_on_diff(element=new_child, status='Added', methods=methods)
|
|
81
|
+
|
|
87
82
|
def add_element_on_diff(self, element: Element, status: Literal['Added', 'Changed', 'Removed'], methods: dict[str, dict[str, Any]]):
|
|
88
83
|
self.differences[element.uuid] = {
|
|
89
84
|
'parent': element.parent.uuid if element.parent else None,
|
|
@@ -94,4 +89,4 @@ class TemplateDiff: # pragma: no cover
|
|
|
94
89
|
if status != 'Removed':
|
|
95
90
|
self.differences[element.uuid]['methods'] = {**methods}
|
|
96
91
|
|
|
97
|
-
element.remove_element_methods()
|
|
92
|
+
element.remove_element_methods()
|
|
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.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/favicon/apple-touch-icon.png
RENAMED
|
File without changes
|
{pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/favicon/favicon-16x16.png
RENAMED
|
File without changes
|
{pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/pyweber/static/favicon/favicon-32x32.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260430}/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.dev20260428 → pyweber-1.2.0.dev20260430}/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
|