pyweber 1.2.0.dev20260428__tar.gz → 1.2.0.dev20260429__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.
Files changed (88) hide show
  1. {pyweber-1.2.0.dev20260428/pyweber.egg-info → pyweber-1.2.0.dev20260429}/PKG-INFO +1 -1
  2. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyproject.toml +1 -1
  3. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/core/element.py +14 -1
  4. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/core/template.py +1 -18
  5. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/element.py +3 -4
  6. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/template_diff.py +19 -24
  7. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429/pyweber.egg-info}/PKG-INFO +1 -1
  8. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/LICENSE +0 -0
  9. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/MANIFEST.in +0 -0
  10. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/README.md +0 -0
  11. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/__init__.py +0 -0
  12. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/admin/index.html +0 -0
  13. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/admin/src/script.js +0 -0
  14. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/admin/src/style.css +0 -0
  15. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/cli/__init__.py +0 -0
  16. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/cli/commands.py +0 -0
  17. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/components/__init__.py +0 -0
  18. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/components/form.py +0 -0
  19. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/components/general.py +0 -0
  20. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/components/input.py +0 -0
  21. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/config/__init__.py +0 -0
  22. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/config/config.py +0 -0
  23. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/connection/__init__.py +0 -0
  24. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/connection/http.py +0 -0
  25. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/connection/reload.py +0 -0
  26. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/connection/selector.py +0 -0
  27. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/connection/session.py +0 -0
  28. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/connection/websocket.py +0 -0
  29. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/core/__init__.py +0 -0
  30. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/core/events.py +0 -0
  31. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/core/window.py +0 -0
  32. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/__init__.py +0 -0
  33. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/cookies.py +0 -0
  34. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/create_app.py +0 -0
  35. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/error_pages.py +0 -0
  36. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/field.py +0 -0
  37. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/field_storage.py +0 -0
  38. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/file.py +0 -0
  39. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/file_stream.py +0 -0
  40. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/headers.py +0 -0
  41. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/middleware.py +0 -0
  42. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/openapi.py +0 -0
  43. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/request.py +0 -0
  44. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/response.py +0 -0
  45. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/routes.py +0 -0
  46. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/run.py +0 -0
  47. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/strem_stats.py +0 -0
  48. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/task_manager.py +0 -0
  49. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/models/ws_message.py +0 -0
  50. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/pyweber/__init__.py +0 -0
  51. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/pyweber/pyweber.py +0 -0
  52. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/.gitignore +0 -0
  53. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/config.toml +0 -0
  54. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/css.css +0 -0
  55. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/docs.html +0 -0
  56. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/favicon/android-chrome-192x192.png +0 -0
  57. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/favicon/android-chrome-512x512.png +0 -0
  58. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/favicon/apple-touch-icon.png +0 -0
  59. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/favicon/favicon-16x16.png +0 -0
  60. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/favicon/favicon-32x32.png +0 -0
  61. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/favicon/favicon.ico +0 -0
  62. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/favicon/pyweber.png +0 -0
  63. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/favicon/site.webmanifest +0 -0
  64. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/handlers.js +0 -0
  65. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/html.html +0 -0
  66. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/html401.html +0 -0
  67. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/html404.html +0 -0
  68. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/html500.html +0 -0
  69. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/js.js +0 -0
  70. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/loading.html +0 -0
  71. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/main.py +0 -0
  72. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/pyweber.css +0 -0
  73. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/static/update.py +0 -0
  74. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/utils/__init__.py +0 -0
  75. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/utils/exceptions.py +0 -0
  76. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/utils/loads.py +0 -0
  77. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/utils/types.py +0 -0
  78. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber/utils/utils.py +0 -0
  79. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber.egg-info/SOURCES.txt +0 -0
  80. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber.egg-info/dependency_links.txt +0 -0
  81. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber.egg-info/entry_points.txt +0 -0
  82. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber.egg-info/requires.txt +0 -0
  83. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/pyweber.egg-info/top_level.txt +0 -0
  84. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/setup.cfg +0 -0
  85. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/tests/test_config.py +0 -0
  86. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/tests/test_cookies.py +0 -0
  87. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/tests/test_response.py +0 -0
  88. {pyweber-1.2.0.dev20260428 → pyweber-1.2.0.dev20260429}/tests/test_template_diff.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyweber
3
- Version: 1.2.0.dev20260428
3
+ Version: 1.2.0.dev20260429
4
4
  Summary: A lightweight Python framework for building and managing web applications.
5
5
  Author-email: DevPythonMZ <pypi.dev@gmail.com>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pyweber"
7
- version = "1.2.0.dev20260428"
7
+ version = "1.2.0.dev20260429"
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 (
@@ -339,7 +341,7 @@ class Element(ElementConstrutor): # pragma: no cover
339
341
 
340
342
  @classmethod
341
343
  def from_html(cls, html: str, include_uuid: bool = True, **kwargs):
342
- HtmlElement = fromstring(html.strip())
344
+ HtmlElement = fromstring(cls.read_file(html).strip())
343
345
  return cls._create_element(HTMLElement=HtmlElement, parent=None, include_uuid=include_uuid, **kwargs)
344
346
 
345
347
  @classmethod
@@ -422,6 +424,16 @@ class Element(ElementConstrutor): # pragma: no cover
422
424
  except: pass
423
425
  return element
424
426
 
427
+ @classmethod
428
+ def read_file(cls, file_path: str) -> str:
429
+ if file_path.endswith('.html'):
430
+ path = os.path.join('templates', file_path) if not os.path.isfile(file_path) else file_path
431
+
432
+ try: return LoadStaticFiles(path=path).load
433
+ except FileNotFoundError: raise FileNotFoundError(f'{path} not found, please include on templates path')
434
+
435
+ return file_path
436
+
425
437
  def update(self):
426
438
  raise NotImplementedError
427
439
 
@@ -433,5 +445,6 @@ class Element(ElementConstrutor): # pragma: no cover
433
445
  else:
434
446
  return obj
435
447
 
448
+
436
449
  def __str__(self):
437
450
  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 = self.__read_file(file_path=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.get_attr('type', None) == 'checkbox':
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(self, content: str, **kwargs):
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 = self.to_html(element=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
- self.add_element_on_diff(element=old_child, status='Removed', methods=methods)
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
- self.add_element_on_diff(element=new_child, status='Added', methods=methods)
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()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyweber
3
- Version: 1.2.0.dev20260428
3
+ Version: 1.2.0.dev20260429
4
4
  Summary: A lightweight Python framework for building and managing web applications.
5
5
  Author-email: DevPythonMZ <pypi.dev@gmail.com>
6
6
  License-Expression: MIT