dars-framework 1.1.2__tar.gz → 1.1.4__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 (109) hide show
  1. {dars_framework-1.1.2 → dars_framework-1.1.4}/MANIFEST.in +1 -1
  2. {dars_framework-1.1.2/dars_framework.egg-info → dars_framework-1.1.4}/PKG-INFO +7 -15
  3. {dars_framework-1.1.2 → dars_framework-1.1.4}/README.md +6 -14
  4. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/cli/main.py +0 -1
  5. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/cli/translations.py +4 -0
  6. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/core/app.py +9 -5
  7. dars_framework-1.1.4/dars/dars_tests/run_tests.py +262 -0
  8. dars_framework-1.1.4/dars/dars_tests/tests/test_advanced_components.py +69 -0
  9. dars_framework-1.1.4/dars/dars_tests/tests/test_basic_components.py +88 -0
  10. dars_framework-1.1.4/dars/dars_tests/tests/test_core_and_cli.py +17 -0
  11. dars_framework-1.1.4/dars/dars_tests/tests/test_layout_components.py +58 -0
  12. dars_framework-1.1.4/dars/dars_tests/tests/test_version_check.py +21 -0
  13. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/docs/app.md +112 -0
  14. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/docs/components.md +31 -30
  15. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/docs/getting_started.md +1 -0
  16. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/docs/index.md +18 -16
  17. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/exporters/web/html_css_js.py +28 -24
  18. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/advanced/SimpleDashboard/dashboard.py +1 -4
  19. dars_framework-1.1.4/dars/templates/examples/advanced/SimpleModermWeb/modern_web_app.py +452 -0
  20. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/basic/HelloWorld/hello_world.py +1 -1
  21. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/version.py +2 -2
  22. {dars_framework-1.1.2 → dars_framework-1.1.4/dars_framework.egg-info}/PKG-INFO +7 -15
  23. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars_framework.egg-info/SOURCES.txt +7 -0
  24. {dars_framework-1.1.2 → dars_framework-1.1.4}/pyproject.toml +1 -1
  25. {dars_framework-1.1.2 → dars_framework-1.1.4}/LICENSE +0 -0
  26. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/__init__.py +0 -0
  27. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/all.py +0 -0
  28. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/cli/__init__.py +0 -0
  29. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/cli/hot_reload.py +0 -0
  30. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/cli/preview.py +0 -0
  31. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/__init__.py +0 -0
  32. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/advanced/__init__.py +0 -0
  33. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/advanced/accordion.py +0 -0
  34. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/advanced/card.py +0 -0
  35. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/advanced/modal.py +0 -0
  36. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/advanced/navbar.py +0 -0
  37. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/advanced/table.py +0 -0
  38. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/advanced/tabs.py +0 -0
  39. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/__init__.py +0 -0
  40. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/button.py +0 -0
  41. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/checkbox.py +0 -0
  42. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/container.py +0 -0
  43. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/datepicker.py +0 -0
  44. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/image.py +0 -0
  45. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/input.py +0 -0
  46. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/link.py +0 -0
  47. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/markdown.py +0 -0
  48. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/page.py +0 -0
  49. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/progressbar.py +0 -0
  50. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/radiobutton.py +0 -0
  51. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/select.py +0 -0
  52. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/slider.py +0 -0
  53. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/spinner.py +0 -0
  54. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/text.py +0 -0
  55. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/textarea.py +0 -0
  56. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/basic/tooltip.py +0 -0
  57. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/layout/__init__.py +0 -0
  58. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/layout/anchor.py +0 -0
  59. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/layout/flex.py +0 -0
  60. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/components/layout/grid.py +0 -0
  61. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/core/__init__.py +0 -0
  62. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/core/component.py +0 -0
  63. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/core/events.py +0 -0
  64. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/core/properties.py +0 -0
  65. {dars_framework-1.1.2/dars/templates/examples/advanced/SimpleModermWeb → dars_framework-1.1.4/dars/dars_tests/apps_test}/modern_web_app.py +0 -0
  66. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/docs/__init__.py +0 -0
  67. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/docs/cli.md +0 -0
  68. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/docs/custom_components.md +0 -0
  69. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/docs/events.md +0 -0
  70. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/docs/exporters.md +0 -0
  71. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/docs/scripts.md +0 -0
  72. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/exporters/__init__.py +0 -0
  73. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/exporters/base.py +0 -0
  74. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/exporters/web/OLD/html_css_js_OLD4.py +0 -0
  75. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/exporters/web/OLD/html_css_js_old.py +0 -0
  76. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/exporters/web/OLD/html_css_js_old2.py +0 -0
  77. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/exporters/web/__init__.py +0 -0
  78. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/scripts/__init__.py +0 -0
  79. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/scripts/dscript.py +0 -0
  80. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/scripts/script.py +0 -0
  81. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/__init__.py +0 -0
  82. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/__pycache__/__init__.cpython-311.pyc +0 -0
  83. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/README.md +0 -0
  84. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/__pycache__/dynamic_event_demo.cpython-311.pyc +0 -0
  85. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/advanced/Modal_Demo/advanced_modal_demo.py +0 -0
  86. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/advanced/VariousComponents/all_components_demo.py +0 -0
  87. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/advanced/__init__.py +0 -0
  88. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/basic/Forms/form_components.py +0 -0
  89. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/basic/Forms/simple_form.py +0 -0
  90. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/basic/Layouts/flex_layout_responsive.py +0 -0
  91. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/basic/Layouts/grid_layout_responsive.py +0 -0
  92. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/basic/Layouts/layout_multipage_demo.py +0 -0
  93. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/basic/Multipage/multipage_example.py +0 -0
  94. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/basic/PWA/icon-192x192.png +0 -0
  95. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/basic/PWA/icon-512x512.png +0 -0
  96. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/basic/PWA/pwa_custom_icons.py +0 -0
  97. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/basic/__init__.py +0 -0
  98. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/demo/__pycache__/complete_app.cpython-311.pyc +0 -0
  99. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/demo/complete_app.py +0 -0
  100. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/markdown/MarkdownTemplate/README.md +0 -0
  101. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/markdown/MarkdownTemplate/markdown_template.py +0 -0
  102. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/markdown/MarkdownTemplate/other_docs.md +0 -0
  103. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/examples/markdown/__init__.py +0 -0
  104. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars/templates/html/__init__.py +0 -0
  105. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars_framework.egg-info/dependency_links.txt +0 -0
  106. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars_framework.egg-info/entry_points.txt +0 -0
  107. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars_framework.egg-info/requires.txt +0 -0
  108. {dars_framework-1.1.2 → dars_framework-1.1.4}/dars_framework.egg-info/top_level.txt +0 -0
  109. {dars_framework-1.1.2 → dars_framework-1.1.4}/setup.cfg +0 -0
@@ -3,4 +3,4 @@ include LICENSE
3
3
  recursive-include dars/templates *
4
4
  recursive-include dars/docs *
5
5
  recursive-include dars *.json
6
- recursive-include dars *.md
6
+ recursive-include dars *.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dars-framework
3
- Version: 1.1.2
3
+ Version: 1.1.4
4
4
  Summary: Dars is a Python UI framework for building modern, interactive web apps with only Python code. Write your interface in Python, export it to static HTML/CSS/JS, and deploy anywhere.
5
5
  Author-email: ztamdev <zondax2009@gmail.com>
6
6
  License: MIT License
@@ -51,10 +51,10 @@ Try dars without installing nothing just visit the [Dars Playground](https://dar
51
51
  - Preview instantly with hot-reload using `app.rTimeCompile()`.
52
52
  - Export your app to static web files with a single CLI command.
53
53
  - Use multipage, layouts, scripts, and more—see docs for advanced features.
54
- - For mor information visit the [Documentation](dars/docs/index.md)
54
+ - For mor information visit the [Documentation](https://ztamdev.github.io/Dars-Framework/documentation.html)
55
55
 
56
56
  ## Quick Example: Your First App
57
- > Note: this is an single page example but you can build multipage apps with Page component see the [Components Documentation](dars/docs/components.md) to know more.
57
+ > Note: this is an single page example but you can build multipage apps with Page component see the [Components Documentation](https://ztamdev.github.io/Dars-Framework/documentation.html#dars-components-documentation) to know more.
58
58
 
59
59
  ```python
60
60
  from dars import App, Container, Text, Button, InlineScript
@@ -109,18 +109,10 @@ if __name__ == "__main__":
109
109
  | `dars --help` | Show help and all CLI options |
110
110
 
111
111
  ## More
112
- - [Project Roadmap](ROADMAP.md)
113
- - [Getting Started](dars/docs/getting_started.md)
114
- - [App Class and PWA](dars/docs/app.md)
115
- - [Components Documentation](dars/docs/components.md)
116
- - [Custom Components](dars/docs/custom_components.md)
117
- - [Event Handling](dars/docs/events.md)
118
- - [Exporters](dars/docs/exporters.md)
119
- - [Scripts System](dars/docs/scripts.md)
120
- - [CLI usage and commands](dars/docs/cli.md)
121
- - [Project Structure](STRUCTURE.md)
122
- - [Architecture](DARS_ARCHITECTURE.md)
123
- - [Installation Guide](INSTALL.md)
112
+
113
+ - Visit dars [official website](https://ztamdev.github.io/Dars-Framework/)
114
+ - Visit the dars official [Documentation](https://ztamdev.github.io/Dars-Framework/documentation.html) now on separate website.
115
+ - Try dars without installing nothing just visit the [Dars Playground](https://dars-playground.vercel.app/)
124
116
 
125
117
  ## Local Execution and Live Preview
126
118
 
@@ -15,10 +15,10 @@ Try dars without installing nothing just visit the [Dars Playground](https://dar
15
15
  - Preview instantly with hot-reload using `app.rTimeCompile()`.
16
16
  - Export your app to static web files with a single CLI command.
17
17
  - Use multipage, layouts, scripts, and more—see docs for advanced features.
18
- - For mor information visit the [Documentation](dars/docs/index.md)
18
+ - For mor information visit the [Documentation](https://ztamdev.github.io/Dars-Framework/documentation.html)
19
19
 
20
20
  ## Quick Example: Your First App
21
- > Note: this is an single page example but you can build multipage apps with Page component see the [Components Documentation](dars/docs/components.md) to know more.
21
+ > Note: this is an single page example but you can build multipage apps with Page component see the [Components Documentation](https://ztamdev.github.io/Dars-Framework/documentation.html#dars-components-documentation) to know more.
22
22
 
23
23
  ```python
24
24
  from dars import App, Container, Text, Button, InlineScript
@@ -73,18 +73,10 @@ if __name__ == "__main__":
73
73
  | `dars --help` | Show help and all CLI options |
74
74
 
75
75
  ## More
76
- - [Project Roadmap](ROADMAP.md)
77
- - [Getting Started](dars/docs/getting_started.md)
78
- - [App Class and PWA](dars/docs/app.md)
79
- - [Components Documentation](dars/docs/components.md)
80
- - [Custom Components](dars/docs/custom_components.md)
81
- - [Event Handling](dars/docs/events.md)
82
- - [Exporters](dars/docs/exporters.md)
83
- - [Scripts System](dars/docs/scripts.md)
84
- - [CLI usage and commands](dars/docs/cli.md)
85
- - [Project Structure](STRUCTURE.md)
86
- - [Architecture](DARS_ARCHITECTURE.md)
87
- - [Installation Guide](INSTALL.md)
76
+
77
+ - Visit dars [official website](https://ztamdev.github.io/Dars-Framework/)
78
+ - Visit the dars official [Documentation](https://ztamdev.github.io/Dars-Framework/documentation.html) now on separate website.
79
+ - Try dars without installing nothing just visit the [Dars Playground](https://dars-playground.vercel.app/)
88
80
 
89
81
  ## Local Execution and Live Preview
90
82
 
@@ -368,7 +368,6 @@ class DarsExporter:
368
368
  info_table.add_row(translator.get('scripts'), str(stats['scripts_count']))
369
369
  info_table.add_row(translator.get('global_styles'), str(stats['global_styles_count']))
370
370
  info_table.add_row(translator.get('theme'), app.config.get('theme', 'light'))
371
- info_table.add_row(translator.get('responsive'), str(app.config.get('responsive', True)))
372
371
 
373
372
  console.print(info_table)
374
373
 
@@ -17,6 +17,8 @@ translations = {
17
17
  'info_help': "Show application information",
18
18
  'formats_help': "Show supported formats",
19
19
  'preview_help': "Preview information",
20
+ 'property_column': "Property",
21
+ 'value_column': "Value",
20
22
  'preview_cmd_help': "Preview exported application",
21
23
  'init_help': "Create a Dars project",
22
24
  'template_not_found': "Template '{template}' not found",
@@ -171,6 +173,8 @@ translations = {
171
173
  'preview_help': "Información de preview",
172
174
  'preview_cmd_help': "Previsualizar aplicación exportada",
173
175
  'init_help': "Crea un proyecto Dars",
176
+ 'property_column': "Propiedad",
177
+ 'value_column': "Valor",
174
178
 
175
179
  # Export command
176
180
  'file_help': "Archivo Python con la aplicación Dars",
@@ -127,7 +127,7 @@ class Page:
127
127
  class App:
128
128
  """Main class that represents a Dars application"""
129
129
 
130
- def rTimeCompile(self, exporter=None, port=None, add_file_types=".py, .js, .css"):
130
+ def rTimeCompile(self, exporter=None, port=None, add_file_types=".py, .js, .css", watchfiledialog=False):
131
131
  """
132
132
  Generates a quick preview of the app on a local server using an exporter
133
133
  (default: HTMLCSSJSExporter) and serving the files from a temporary directory.
@@ -145,6 +145,8 @@ class App:
145
145
  import shutil
146
146
  import traceback
147
147
 
148
+ self.watchfiledialog = watchfiledialog
149
+
148
150
  @contextmanager
149
151
  def pushd(path):
150
152
  """Cambia temporalmente el cwd y lo restaura al salir."""
@@ -425,11 +427,13 @@ class App:
425
427
  subtitle=f"Project root: {os.path.basename(project_root)}",
426
428
  border_style="magenta"
427
429
  )
428
- console.print(panel)
430
+ if self.watchfiledialog:
431
+ console.print(panel)
429
432
  else:
430
- print(f"[Dars] Watching {len(files_to_watch)} files in {project_root}:")
431
- for f in files_to_watch:
432
- print(" -", os.path.relpath(f, project_root))
433
+ if self.watchfiledialog:
434
+ print(f"[Dars] Watching {len(files_to_watch)} files in {project_root}:")
435
+ for f in files_to_watch:
436
+ print(" -", os.path.relpath(f, project_root))
433
437
 
434
438
  # Loop principal: espera a Ctrl+C
435
439
  while not shutdown_event.is_set():
@@ -0,0 +1,262 @@
1
+ # Runner that executes the test files and prints a colored report using rich
2
+ import runpy, glob, importlib.util, os, sys, traceback, subprocess, time, threading
3
+ import requests
4
+ import signal
5
+ import webbrowser
6
+ import shutil
7
+ from rich.console import Console
8
+ from rich.table import Table
9
+ from rich.panel import Panel
10
+ from rich.prompt import Prompt
11
+
12
+ console = Console()
13
+
14
+ def run_unit_tests(unit_test_paths=None):
15
+ """Run unit test files, optionally from specific paths"""
16
+ if unit_test_paths is None:
17
+ # Default behavior: run all tests in tests directory
18
+ tests = sorted(glob.glob(os.path.join(os.path.dirname(__file__), 'tests', 'test_*.py')))
19
+ else:
20
+ # Use provided test paths
21
+ tests = unit_test_paths
22
+
23
+ results = []
24
+ for t in tests:
25
+ name = os.path.basename(t)
26
+ try:
27
+ console.print(Panel(f'Running {name}', style='cyan'))
28
+ ns = runpy.run_path(t, run_name='__main__')
29
+ results.append((name, True, None))
30
+ console.print(f'[green]PASS[/green] {name}')
31
+ except Exception as e:
32
+ results.append((name, False, traceback.format_exc()))
33
+ console.print(f'[red]FAIL[/red] {name}')
34
+ console.print(traceback.format_exc())
35
+ return results
36
+
37
+ def check_server(port=8000, timeout=10):
38
+ """Check if the server is running on the given port"""
39
+ start_time = time.time()
40
+ while time.time() - start_time < timeout:
41
+ try:
42
+ response = requests.get(f'http://localhost:{port}', timeout=2)
43
+ if response.status_code < 500:
44
+ return True
45
+ except requests.exceptions.RequestException:
46
+ time.sleep(0.5)
47
+ return False
48
+
49
+ def run_app_with_timeout(app_file, timeout=15):
50
+ """Run a Dars app with rTimeCompile and capture its output with a timeout"""
51
+ try:
52
+ # Redirigir stdout y stderr a archivos temporales o a devnull
53
+ with open(os.devnull, 'w') as devnull:
54
+ process = subprocess.Popen(
55
+ [sys.executable, app_file],
56
+ stdout=devnull, # Redirigir stdout a devnull
57
+ stderr=devnull, # Redirigir stderr a devnull
58
+ cwd=os.path.dirname(app_file),
59
+ env={**os.environ, 'PYTHONIOENCODING': 'utf-8'}, # Establecer codificación
60
+ )
61
+
62
+ # Esperar a que el servidor se inicie o timeout
63
+ server_started = False
64
+ start_time = time.time()
65
+
66
+ while time.time() - start_time < timeout:
67
+ if check_server(8000, 2):
68
+ server_started = True
69
+ break
70
+ time.sleep(1)
71
+
72
+ # Devolver resultados
73
+ return {
74
+ 'success': server_started,
75
+ 'process': process,
76
+ 'stdout': '',
77
+ 'stderr': ''
78
+ }
79
+
80
+ except Exception as e:
81
+ return {
82
+ 'success': False,
83
+ 'error': str(e),
84
+ 'stdout': '',
85
+ 'stderr': ''
86
+ }
87
+
88
+ def safe_read_file(file_path):
89
+ """Leer un archivo de forma segura manejando diferentes codificaciones"""
90
+ encodings = ['utf-8', 'latin-1', 'cp1252', 'iso-8859-1']
91
+
92
+ for encoding in encodings:
93
+ try:
94
+ with open(file_path, 'r', encoding=encoding) as f:
95
+ return f.read()
96
+ except UnicodeDecodeError:
97
+ continue
98
+
99
+ # Si todas las codificaciones fallan, usar modo binario con reemplazo de errores
100
+ with open(file_path, 'rb') as f:
101
+ return f.read().decode('utf-8', errors='replace')
102
+
103
+ def run_app_tests(app_test_paths=None):
104
+ """Run Dars application tests that use rTimeCompile, optionally from specific paths"""
105
+ if app_test_paths is None:
106
+ # Default behavior: run all apps in apps_test directory
107
+ apps_test_dir = os.path.join(os.path.dirname(__file__), 'apps_test')
108
+ if not os.path.exists(apps_test_dir):
109
+ console.print(f"[yellow]apps_test directory not found: {apps_test_dir}[/yellow]")
110
+ return []
111
+
112
+ apps = sorted(glob.glob(os.path.join(apps_test_dir, '*.py')))
113
+ else:
114
+ # Use provided app paths
115
+ apps = app_test_paths
116
+
117
+ results = []
118
+
119
+ for app_file in apps:
120
+ name = os.path.basename(app_file)
121
+ try:
122
+ console.print(Panel(f'Testing Dars App: {name}', style='magenta'))
123
+
124
+ # Verificar si la aplicación usa rTimeCompile de forma segura
125
+ content = safe_read_file(app_file)
126
+ uses_rTimeCompile = 'rTimeCompile' in content
127
+
128
+ if not uses_rTimeCompile:
129
+ console.print(f"[yellow]Skipping {name} - does not use rTimeCompile[/yellow]")
130
+ continue
131
+
132
+ # Ejecutar la aplicación con timeout
133
+ result = run_app_with_timeout(app_file, timeout=20)
134
+
135
+ if result['success']:
136
+ # Éxito: el servidor se inició correctamente
137
+ results.append((name, True, "App started server successfully on port 8000"))
138
+ console.print(f'[green]PASS[/green] {name}')
139
+
140
+ # Abrir el navegador para verificación visual
141
+ console.print("[green]Opening browser for visual verification...[/green]")
142
+ webbrowser.open('http://localhost:8000')
143
+
144
+ # Preguntar al usuario si quiere terminar el proceso
145
+ console.print("\n[bold]Please verify the application in your browser.[/bold]")
146
+ console.print("After verification, you can:")
147
+ console.print("1. Press 'y' to terminate the process and continue with tests")
148
+ console.print("2. Press 'n' to keep the server running and continue")
149
+
150
+ response = Prompt.ask("\nTerminate process and continue?", choices=["y", "n"], default="y")
151
+
152
+ if response.lower() == "y":
153
+ # Terminar el proceso
154
+ if 'process' in result and result['process'].poll() is None:
155
+ console.print("[yellow]Terminating app process...[/yellow]")
156
+ try:
157
+ # Enviar señal de interrupción (equivalente a Ctrl+C)
158
+ if os.name == 'nt': # Windows
159
+ result['process'].terminate()
160
+ else: # Unix
161
+ result['process'].send_signal(signal.SIGINT)
162
+
163
+ # Esperar a que termine
164
+ result['process'].wait(timeout=10)
165
+ console.print("[green]App process terminated successfully[/green]")
166
+
167
+ # Limpiar carpeta dars_preview
168
+ preview_dir = os.path.join(os.path.dirname(app_file), "dars_preview")
169
+ if os.path.exists(preview_dir):
170
+ shutil.rmtree(preview_dir)
171
+ console.print("[green]Preview directory cleaned up[/green]")
172
+
173
+ except:
174
+ console.print("[red]Force killing app process...[/red]")
175
+ result['process'].kill()
176
+ else:
177
+ console.print("[yellow]Keeping server running...[/yellow]")
178
+ else:
179
+ # Fallo: el servidor no se inició
180
+ error_msg = result['stderr'] or result['stdout'] or "Unknown error"
181
+ results.append((name, False, error_msg))
182
+ console.print(f'[red]FAIL[/red] {name}: {error_msg}')
183
+
184
+ # Terminar el proceso si todavía está ejecutándose (solo si no elegimos mantenerlo)
185
+ if 'process' in result and result['process'].poll() is None:
186
+ console.print("[yellow]Terminating app process...[/yellow]")
187
+ try:
188
+ # Enviar señal de interrupción (equivalente a Ctrl+C)
189
+ if os.name == 'nt': # Windows
190
+ result['process'].terminate()
191
+ else: # Unix
192
+ result['process'].send_signal(signal.SIGINT)
193
+
194
+ # Esperar a que termine
195
+ result['process'].wait(timeout=10)
196
+ console.print("[green]App process terminated successfully[/green]")
197
+
198
+ # Limpiar carpeta dars_preview
199
+ preview_dir = os.path.join(os.path.dirname(app_file), "dars_preview")
200
+ if os.path.exists(preview_dir):
201
+ shutil.rmtree(preview_dir)
202
+ console.print("[green]Preview directory cleaned up[/green]")
203
+
204
+ except:
205
+ console.print("[red]Force killing app process...[/red]")
206
+ result['process'].kill()
207
+
208
+ except Exception as e:
209
+ results.append((name, False, str(e)))
210
+ console.print(f'[red]FAIL[/red] {name}: {e}')
211
+
212
+ return results
213
+
214
+ def main(unit_test_paths=None, app_test_paths=None):
215
+ """
216
+ Run Dars test suite with optional specific test paths
217
+
218
+ Args:
219
+ unit_test_paths (list): Optional list of paths to unit test files
220
+ app_test_paths (list): Optional list of paths to application test files
221
+ """
222
+ # Run unit tests
223
+ console.print(Panel("Running Unit Tests", style="cyan"))
224
+ unit_results = run_unit_tests(unit_test_paths)
225
+
226
+ # Run app tests
227
+ console.print(Panel("Running App Tests (rTimeCompile)", style="magenta"))
228
+ app_results = run_app_tests(app_test_paths)
229
+
230
+ # Combine results
231
+ all_results = unit_results + app_results
232
+
233
+ # Print results table
234
+ table = Table(title='Dars Test Suite Results')
235
+ table.add_column('Test File')
236
+ table.add_column('Result')
237
+ table.add_column('Details', overflow='fold')
238
+
239
+ for name, ok, details in all_results:
240
+ table.add_row(name, '[green]PASS[/green]' if ok else '[red]FAIL[/red]', details or '')
241
+
242
+ console.print(table)
243
+
244
+ # Exit code
245
+ any_fail = any(not ok for _, ok, _ in all_results)
246
+ if any_fail:
247
+ console.print('[bold red]Some tests failed.[/bold red]')
248
+ sys.exit(1)
249
+ else:
250
+ console.print('[bold green]All tests passed.[/bold green]')
251
+
252
+ if __name__ == '__main__':
253
+ # Parse command line arguments for custom test paths
254
+ import argparse
255
+ parser = argparse.ArgumentParser(description='Run Dars Framework tests')
256
+ parser.add_argument('--unit-tests', nargs='+', help='Paths to specific unit test files')
257
+ parser.add_argument('--app-tests', nargs='+', help='Paths to specific application test files')
258
+
259
+ args = parser.parse_args()
260
+
261
+ # Run tests with optional paths
262
+ main(unit_test_paths=args.unit_tests, app_test_paths=args.app_tests)
@@ -0,0 +1,69 @@
1
+ import importlib, inspect, sys, os
2
+ from dars.core.component import Component
3
+ from dars.components.basic.text import Text
4
+
5
+ project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'dars'))
6
+ if project_root not in sys.path:
7
+ sys.path.insert(0, project_root)
8
+
9
+ failures = []
10
+
11
+ def test_advanced_components():
12
+ base_pkg = 'dars.components.advanced'
13
+ try:
14
+ pkg = importlib.import_module(base_pkg)
15
+ except Exception as e:
16
+ raise AssertionError(f'Could not import {base_pkg}: {e}')
17
+
18
+ pkg_path = os.path.dirname(pkg.__file__)
19
+ for fname in os.listdir(pkg_path):
20
+ if not fname.endswith('.py') or fname.startswith('__'):
21
+ continue
22
+
23
+ modname = f"{base_pkg}.{fname[:-3]}"
24
+ try:
25
+ m = importlib.import_module(modname)
26
+ except Exception as e:
27
+ failures.append((modname, 'import', repr(e)))
28
+ continue
29
+
30
+ for _name, obj in inspect.getmembers(m, inspect.isclass):
31
+ try:
32
+ if obj is Component:
33
+ continue
34
+ if issubclass(obj, Component):
35
+ # Proporciona argumentos específicos para cada componente avanzado
36
+ if _name == 'Accordion':
37
+ instance = obj(sections=[{'title': 'Test', 'content': 'Content'}])
38
+ elif _name == 'Table':
39
+ instance = obj(columns=['Col1'], data=[['Data1']])
40
+ elif _name == 'Tabs':
41
+ instance = obj(tabs=['Tab1'], panels=[Text('Panel1')])
42
+ elif _name == 'Card':
43
+ instance = obj(title='Test Card')
44
+ elif _name == 'Modal':
45
+ instance = obj(title='Test Modal')
46
+ elif _name == 'Navbar':
47
+ instance = obj(brand='Test Navbar')
48
+ else:
49
+ # Intenta con argumentos mínimos para otros componentes
50
+ try:
51
+ instance = obj()
52
+ except TypeError:
53
+ instance = obj(id='test')
54
+
55
+ # Verifica que la instancia se creó correctamente
56
+ assert instance is not None, f"Failed to create instance of {_name}"
57
+
58
+ except Exception as e:
59
+ failures.append((f"{modname}.{_name}", 'init', repr(e)))
60
+
61
+ assert not failures, failures
62
+
63
+ if __name__ == '__main__':
64
+ try:
65
+ test_advanced_components()
66
+ print('test_advanced_components: OK')
67
+ except AssertionError as e:
68
+ print('test_advanced_components: FAIL', e)
69
+ sys.exit(1)
@@ -0,0 +1,88 @@
1
+ import importlib, inspect, sys, os
2
+ from dars.core.component import Component
3
+
4
+ project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'dars'))
5
+ if project_root not in sys.path:
6
+ sys.path.insert(0, project_root)
7
+
8
+ failures = []
9
+
10
+ def test_basic_components():
11
+ base_pkg = 'dars.components.basic'
12
+ try:
13
+ pkg = importlib.import_module(base_pkg)
14
+ except Exception as e:
15
+ failures.append((base_pkg, 'import', repr(e)))
16
+ return
17
+
18
+ pkg_path = os.path.dirname(pkg.__file__)
19
+ for fname in os.listdir(pkg_path):
20
+ if not fname.endswith('.py') or fname.startswith('__'):
21
+ continue
22
+
23
+ modname = f"{base_pkg}.{fname[:-3]}"
24
+ try:
25
+ m = importlib.import_module(modname)
26
+ except Exception as e:
27
+ failures.append((modname, 'import', repr(e)))
28
+ continue
29
+
30
+ for _name, obj in inspect.getmembers(m, inspect.isclass):
31
+ try:
32
+ if obj is Component:
33
+ continue
34
+ if issubclass(obj, Component):
35
+ # Proporciona argumentos específicos para cada componente
36
+ if _name == 'Image':
37
+ instance = obj(src='test.png')
38
+ elif _name == 'Link':
39
+ instance = obj(text='Test', href='#')
40
+ elif _name == 'Markdown':
41
+ instance = obj(content='# Test')
42
+ elif _name == 'ProgressBar':
43
+ instance = obj(value=50)
44
+ elif _name == 'Tooltip':
45
+ from dars.components.basic.text import Text
46
+ instance = obj(text='Tip', child=Text('Hover me'))
47
+ elif _name == 'Button':
48
+ instance = obj(text='Test Button')
49
+ elif _name == 'Input':
50
+ instance = obj()
51
+ elif _name == 'Textarea':
52
+ instance = obj()
53
+ elif _name == 'Checkbox':
54
+ instance = obj(label='Test Checkbox')
55
+ elif _name == 'RadioButton':
56
+ instance = obj(label='Test Radio', name='test_radio')
57
+ elif _name == 'Select':
58
+ instance = obj(options=[{'value': 'test', 'label': 'Test'}])
59
+ elif _name == 'Slider':
60
+ instance = obj()
61
+ elif _name == 'DatePicker':
62
+ instance = obj()
63
+ elif _name == 'Container':
64
+ instance = obj()
65
+ elif _name == 'Text':
66
+ instance = obj(text='Test Text')
67
+ else:
68
+ # Intenta con argumentos mínimos para otros componentes
69
+ try:
70
+ instance = obj()
71
+ except TypeError:
72
+ instance = obj(id='test', class_name='c', style={})
73
+
74
+ # Verifica que la instancia se creó correctamente
75
+ assert instance is not None, f"Failed to create instance of {_name}"
76
+
77
+ except Exception as e:
78
+ failures.append((f"{modname}.{_name}", 'init', repr(e)))
79
+
80
+ assert not failures, failures
81
+
82
+ if __name__ == '__main__':
83
+ try:
84
+ test_basic_components()
85
+ print('test_basic_components: OK')
86
+ except AssertionError as e:
87
+ print('test_basic_components: FAIL', e)
88
+ sys.exit(1)
@@ -0,0 +1,17 @@
1
+ import importlib, sys, os
2
+ project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'dars'))
3
+ if project_root not in sys.path:
4
+ sys.path.insert(0, project_root)
5
+
6
+ def test_core_imports():
7
+ import dars.core.app as app
8
+ import dars.core.component as component
9
+ import dars.cli.main as cli_main
10
+ # smoke tests: ensure some expected names exist
11
+ assert hasattr(app, 'App') or hasattr(app, 'Page'), 'app module missing App/Page'
12
+ assert hasattr(component, 'Component'), 'component missing Component'
13
+ assert hasattr(cli_main, 'main') or hasattr(cli_main, 'run'), 'cli main missing entrypoint'
14
+ print('core_and_cli: OK')
15
+
16
+ if __name__ == '__main__':
17
+ test_core_imports()
@@ -0,0 +1,58 @@
1
+ import importlib, inspect, sys, os
2
+ from dars.core.component import Component
3
+
4
+ project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'dars'))
5
+ if project_root not in sys.path:
6
+ sys.path.insert(0, project_root)
7
+
8
+ failures = []
9
+
10
+ def test_layout_components():
11
+ base_pkg = 'dars.components.layout'
12
+ try:
13
+ pkg = importlib.import_module(base_pkg)
14
+ except Exception as e:
15
+ raise AssertionError(f'Could not import {base_pkg}: {e}')
16
+
17
+ pkg_path = os.path.dirname(pkg.__file__)
18
+ for fname in os.listdir(pkg_path):
19
+ if not fname.endswith('.py') or fname.startswith('__'):
20
+ continue
21
+
22
+ modname = f"{base_pkg}.{fname[:-3]}"
23
+ try:
24
+ m = importlib.import_module(modname)
25
+ except Exception as e:
26
+ failures.append((modname, 'import', repr(e)))
27
+ continue
28
+
29
+ for _name, obj in inspect.getmembers(m, inspect.isclass):
30
+ try:
31
+ if obj is Component:
32
+ continue
33
+ if issubclass(obj, Component):
34
+ # Intenta crear una instancia con argumentos mínimos
35
+ try:
36
+ instance = obj()
37
+ except TypeError:
38
+ try:
39
+ instance = obj(id='test')
40
+ except Exception as e:
41
+ failures.append((f"{modname}.{_name}", 'init', repr(e)))
42
+
43
+ # Verifica que la instancia se creó correctamente
44
+ if 'instance' in locals():
45
+ assert instance is not None, f"Failed to create instance of {_name}"
46
+
47
+ except Exception as e:
48
+ failures.append((f"{modname}.{_name}", 'inspect', repr(e)))
49
+
50
+ assert not failures, failures
51
+
52
+ if __name__ == '__main__':
53
+ try:
54
+ test_layout_components()
55
+ print('test_layout_components: OK')
56
+ except AssertionError as e:
57
+ print('test_layout_components: FAIL', e)
58
+ sys.exit(1)