botflow-gui 0.0.1__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 (57) hide show
  1. botflow_gui-0.0.1/LICENSE +21 -0
  2. botflow_gui-0.0.1/PKG-INFO +100 -0
  3. botflow_gui-0.0.1/README.md +87 -0
  4. botflow_gui-0.0.1/botflow/__init__.py +53 -0
  5. botflow_gui-0.0.1/botflow/__pycache__/__init__.cpython-312.pyc +0 -0
  6. botflow_gui-0.0.1/botflow/__pycache__/exceptions.cpython-312.pyc +0 -0
  7. botflow_gui-0.0.1/botflow/__pycache__/i18n.cpython-312.pyc +0 -0
  8. botflow_gui-0.0.1/botflow/__pycache__/logger.cpython-312.pyc +0 -0
  9. botflow_gui-0.0.1/botflow/__pycache__/manager.cpython-312.pyc +0 -0
  10. botflow_gui-0.0.1/botflow/__pycache__/pages.cpython-312.pyc +0 -0
  11. botflow_gui-0.0.1/botflow/__pycache__/qss.cpython-312.pyc +0 -0
  12. botflow_gui-0.0.1/botflow/__pycache__/resolver.cpython-312.pyc +0 -0
  13. botflow_gui-0.0.1/botflow/__pycache__/runtime.cpython-312.pyc +0 -0
  14. botflow_gui-0.0.1/botflow/__pycache__/threads.cpython-312.pyc +0 -0
  15. botflow_gui-0.0.1/botflow/__pycache__/types.cpython-312.pyc +0 -0
  16. botflow_gui-0.0.1/botflow/__pycache__/widgets.cpython-312.pyc +0 -0
  17. botflow_gui-0.0.1/botflow/__pycache__/workers.cpython-312.pyc +0 -0
  18. botflow_gui-0.0.1/botflow/__pyinstaller/__init__.py +0 -0
  19. botflow_gui-0.0.1/botflow/__pyinstaller/__pycache__/hook-botflow.cpython-312.pyc +0 -0
  20. botflow_gui-0.0.1/botflow/__pyinstaller/hook-botflow.py +10 -0
  21. botflow_gui-0.0.1/botflow/exceptions.py +4 -0
  22. botflow_gui-0.0.1/botflow/i18n.py +57 -0
  23. botflow_gui-0.0.1/botflow/logger.py +45 -0
  24. botflow_gui-0.0.1/botflow/manager.py +318 -0
  25. botflow_gui-0.0.1/botflow/pages.py +117 -0
  26. botflow_gui-0.0.1/botflow/qss.py +21 -0
  27. botflow_gui-0.0.1/botflow/resolver.py +94 -0
  28. botflow_gui-0.0.1/botflow/resources/assets/loading.gif +0 -0
  29. botflow_gui-0.0.1/botflow/resources/locales/en_US/common.json +8 -0
  30. botflow_gui-0.0.1/botflow/resources/locales/en_US/dialogs.json +15 -0
  31. botflow_gui-0.0.1/botflow/resources/locales/en_US/initial_page.json +3 -0
  32. botflow_gui-0.0.1/botflow/resources/locales/en_US/loading.json +3 -0
  33. botflow_gui-0.0.1/botflow/resources/locales/en_US/messages.json +5 -0
  34. botflow_gui-0.0.1/botflow/resources/locales/pt_BR/common.json +8 -0
  35. botflow_gui-0.0.1/botflow/resources/locales/pt_BR/dialogs.json +15 -0
  36. botflow_gui-0.0.1/botflow/resources/locales/pt_BR/initial_page.json +3 -0
  37. botflow_gui-0.0.1/botflow/resources/locales/pt_BR/loading.json +3 -0
  38. botflow_gui-0.0.1/botflow/resources/locales/pt_BR/messages.json +5 -0
  39. botflow_gui-0.0.1/botflow/resources/styles/file_widget.qss +62 -0
  40. botflow_gui-0.0.1/botflow/resources/styles/flow_choice_widget.qss +0 -0
  41. botflow_gui-0.0.1/botflow/resources/styles/flow_manager.qss +51 -0
  42. botflow_gui-0.0.1/botflow/resources/styles/form_widget.qss +40 -0
  43. botflow_gui-0.0.1/botflow/resources/styles/initial_page.qss +30 -0
  44. botflow_gui-0.0.1/botflow/resources/styles/loading_page.qss +37 -0
  45. botflow_gui-0.0.1/botflow/resources/styles/text_widget.qss +33 -0
  46. botflow_gui-0.0.1/botflow/runtime.py +42 -0
  47. botflow_gui-0.0.1/botflow/types.py +87 -0
  48. botflow_gui-0.0.1/botflow/widgets.py +244 -0
  49. botflow_gui-0.0.1/botflow/workers.py +130 -0
  50. botflow_gui-0.0.1/botflow_gui.egg-info/PKG-INFO +100 -0
  51. botflow_gui-0.0.1/botflow_gui.egg-info/SOURCES.txt +55 -0
  52. botflow_gui-0.0.1/botflow_gui.egg-info/dependency_links.txt +1 -0
  53. botflow_gui-0.0.1/botflow_gui.egg-info/entry_points.txt +2 -0
  54. botflow_gui-0.0.1/botflow_gui.egg-info/requires.txt +6 -0
  55. botflow_gui-0.0.1/botflow_gui.egg-info/top_level.txt +1 -0
  56. botflow_gui-0.0.1/pyproject.toml +32 -0
  57. botflow_gui-0.0.1/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Fernando Luiz Fontes
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,100 @@
1
+ Metadata-Version: 2.4
2
+ Name: botflow-gui
3
+ Version: 0.0.1
4
+ Requires-Python: >=3.12
5
+ Description-Content-Type: text/markdown
6
+ License-File: LICENSE
7
+ Requires-Dist: pyside6>=6.9.1
8
+ Provides-Extra: dev
9
+ Requires-Dist: ruff==0.6; extra == "dev"
10
+ Requires-Dist: pytest==9.0.2; extra == "dev"
11
+ Requires-Dist: pyinstaller==6.17.0; extra == "dev"
12
+ Dynamic: license-file
13
+
14
+ # Botflow
15
+
16
+ Botflow is a lightweight Python framework for building automation workflows and bots with a focus on simplicity, modularity, and ease of integration.
17
+
18
+ ## Features
19
+
20
+ - **Workflow Management**: Define complex bot workflows with simple, declarative syntax
21
+ - **Multi-language Support**: Built-in i18n support with locale management
22
+ - **Resource Management**: Centralized handling of themes, assets, and locales
23
+ - **Bundle Support**: PyInstaller integration for creating standalone executables
24
+ - **Qt Integration**: PySide6 support for GUI-based automation
25
+ - **Configuration**: Flexible runtime configuration with environment variables
26
+
27
+ ## Quick Start
28
+
29
+ 1. Install Botflow via pip:
30
+
31
+ ```bash
32
+ pip install botflow
33
+ ```
34
+
35
+ 2. Create a simple bot workflow:
36
+
37
+ ```python
38
+ from botflow import run_application, run_flow_manager, FlowManager, TextStepSpec, FlowSpec
39
+
40
+ RESOURCES_DIR = 'resources'
41
+
42
+
43
+ async def greet_user(ctx):
44
+ name = ctx.data.get('greet_step')
45
+ ctx.logger.info(f'Hello, {name}!')
46
+
47
+
48
+ flow = FlowSpec(
49
+ name='simple_flow',
50
+ steps=[
51
+ TextStepSpec(
52
+ key='greet_step',
53
+ title='Greet User',
54
+ placeholder='Enter your name',
55
+ ),
56
+ ],
57
+ on_finish=[greet_user]
58
+ )
59
+
60
+
61
+ if __name__ == '__main__':
62
+ run_application()
63
+ flow_manager = FlowManager(flow)
64
+ run_flow_manager(flow_manager, window_title='Simple Flow Manager')
65
+ ```
66
+
67
+ 3. Run your bot:
68
+
69
+ ```bash
70
+ python your_bot_script.py
71
+ ```
72
+
73
+ ## How to create a bundle
74
+
75
+ To create a standalone executable bundle of your Botflow application, you can use PyInstaller. Follow these steps:
76
+
77
+ 1. Install PyInstaller:
78
+
79
+ ```bash
80
+ pip install pyinstaller
81
+ ```
82
+
83
+ 2. Create a spec file for your application. You can generate a default spec file using:
84
+
85
+ ```bash
86
+ pyinstaller your_bot_script.py
87
+ ```
88
+
89
+ 3. If you are using your own resources (like themes, locales, etc.), make sure to include them in the spec file. You can modify the `datas` section of the spec file to include your resources directory:
90
+
91
+ ```bash
92
+ pyinstaller your_bot_script.py --add-data "path/to/your/resources:resources"
93
+ ```
94
+
95
+ 4. If you want to specify a custom resources directory for your bundle, you can set the `BUNDLE_RESOURCES_DIR` variable in your main script:
96
+
97
+ ```python
98
+ BUNDLE_RESOURCES_DIR = 'path/to/your/bundle/resources'
99
+ ```
100
+
@@ -0,0 +1,87 @@
1
+ # Botflow
2
+
3
+ Botflow is a lightweight Python framework for building automation workflows and bots with a focus on simplicity, modularity, and ease of integration.
4
+
5
+ ## Features
6
+
7
+ - **Workflow Management**: Define complex bot workflows with simple, declarative syntax
8
+ - **Multi-language Support**: Built-in i18n support with locale management
9
+ - **Resource Management**: Centralized handling of themes, assets, and locales
10
+ - **Bundle Support**: PyInstaller integration for creating standalone executables
11
+ - **Qt Integration**: PySide6 support for GUI-based automation
12
+ - **Configuration**: Flexible runtime configuration with environment variables
13
+
14
+ ## Quick Start
15
+
16
+ 1. Install Botflow via pip:
17
+
18
+ ```bash
19
+ pip install botflow
20
+ ```
21
+
22
+ 2. Create a simple bot workflow:
23
+
24
+ ```python
25
+ from botflow import run_application, run_flow_manager, FlowManager, TextStepSpec, FlowSpec
26
+
27
+ RESOURCES_DIR = 'resources'
28
+
29
+
30
+ async def greet_user(ctx):
31
+ name = ctx.data.get('greet_step')
32
+ ctx.logger.info(f'Hello, {name}!')
33
+
34
+
35
+ flow = FlowSpec(
36
+ name='simple_flow',
37
+ steps=[
38
+ TextStepSpec(
39
+ key='greet_step',
40
+ title='Greet User',
41
+ placeholder='Enter your name',
42
+ ),
43
+ ],
44
+ on_finish=[greet_user]
45
+ )
46
+
47
+
48
+ if __name__ == '__main__':
49
+ run_application()
50
+ flow_manager = FlowManager(flow)
51
+ run_flow_manager(flow_manager, window_title='Simple Flow Manager')
52
+ ```
53
+
54
+ 3. Run your bot:
55
+
56
+ ```bash
57
+ python your_bot_script.py
58
+ ```
59
+
60
+ ## How to create a bundle
61
+
62
+ To create a standalone executable bundle of your Botflow application, you can use PyInstaller. Follow these steps:
63
+
64
+ 1. Install PyInstaller:
65
+
66
+ ```bash
67
+ pip install pyinstaller
68
+ ```
69
+
70
+ 2. Create a spec file for your application. You can generate a default spec file using:
71
+
72
+ ```bash
73
+ pyinstaller your_bot_script.py
74
+ ```
75
+
76
+ 3. If you are using your own resources (like themes, locales, etc.), make sure to include them in the spec file. You can modify the `datas` section of the spec file to include your resources directory:
77
+
78
+ ```bash
79
+ pyinstaller your_bot_script.py --add-data "path/to/your/resources:resources"
80
+ ```
81
+
82
+ 4. If you want to specify a custom resources directory for your bundle, you can set the `BUNDLE_RESOURCES_DIR` variable in your main script:
83
+
84
+ ```python
85
+ BUNDLE_RESOURCES_DIR = 'path/to/your/bundle/resources'
86
+ ```
87
+
@@ -0,0 +1,53 @@
1
+ from botflow.manager import FlowManager
2
+ from botflow.types import FlowSpec
3
+ from botflow.widgets import (
4
+ FileStepSpec,
5
+ FileWidget,
6
+ FormInput,
7
+ FormStepSpec,
8
+ FormWidget,
9
+ TextStepSpec,
10
+ TextWidget,
11
+ )
12
+
13
+ __all__ = [
14
+ 'FlowManager',
15
+ 'FileStepSpec',
16
+ 'FileWidget',
17
+ 'FormInput',
18
+ 'FormStepSpec',
19
+ 'FormWidget',
20
+ 'TextStepSpec',
21
+ 'TextWidget',
22
+ 'FlowSpec',
23
+ ]
24
+
25
+ import sys
26
+ from pathlib import Path
27
+
28
+ from PySide6.QtWidgets import QApplication
29
+
30
+
31
+ def get_hook_dirs():
32
+ return [str(Path(__file__).resolve().with_name('__pyinstaller'))]
33
+
34
+
35
+ def run_application():
36
+ app = QApplication.instance()
37
+ if not app:
38
+ app = QApplication(sys.argv)
39
+ return app
40
+
41
+
42
+ def run_flow_manager(
43
+ flow_manager: FlowManager,
44
+ *,
45
+ width: int = 720,
46
+ height: int = 300,
47
+ window_title: str = 'Flow Manager',
48
+ ):
49
+ app = run_application()
50
+ flow_manager.resize(width, height)
51
+ flow_manager.setWindowTitle(window_title)
52
+ flow_manager.show()
53
+ sys.exit(app.exec())
File without changes
@@ -0,0 +1,10 @@
1
+ from pathlib import Path
2
+
3
+ from PyInstaller.utils.hooks import get_module_file_attribute
4
+
5
+ module_path = get_module_file_attribute('botflow')
6
+ if module_path:
7
+ botflow_dir = Path(module_path).parent
8
+ datas = [(str(botflow_dir / 'resources'), 'lib_resources')]
9
+ else:
10
+ datas = []
@@ -0,0 +1,4 @@
1
+ class PipelineExceptedError(Exception):
2
+ def __init__(self, message: str, popup_message: str | None = None):
3
+ super().__init__(message)
4
+ self.popup_message = popup_message or message
@@ -0,0 +1,57 @@
1
+ import json
2
+ from pathlib import Path
3
+ from typing import Any
4
+
5
+ from botflow.resolver import find_all_locales_dirs
6
+
7
+
8
+ class I18n:
9
+ def __init__(self, catalog: dict[str, Any], lang: str, fallback_lang: str = 'en_US'):
10
+ self.catalog = catalog
11
+ self.lang = lang
12
+ self.fallback_lang = fallback_lang
13
+
14
+ def t(self, key: str, **params: Any) -> str:
15
+ loc = self.lang or self.fallback_lang
16
+
17
+ bucket = self.catalog.get(loc, {})
18
+ v = bucket.get(key)
19
+
20
+ if v is None and self.fallback_lang and self.fallback_lang != loc:
21
+ v = self.catalog.get(self.fallback_lang, {}).get(key)
22
+
23
+ if v is None:
24
+ raise KeyError(f'Missing translation key: {key} (lang={self.lang})')
25
+
26
+ if not isinstance(v, str):
27
+ return str(v)
28
+
29
+ return v.format(**params) if params else v
30
+
31
+ def set_lang(self, lang: str) -> None:
32
+ self.lang = lang
33
+
34
+ @staticmethod
35
+ def from_locales_dirs(lang: str):
36
+ locales_dirs = find_all_locales_dirs()
37
+ catalog: dict[str, dict[str, Any]] = {}
38
+
39
+ for locales_dir in locales_dirs if isinstance(locales_dirs, list) else [locales_dirs]:
40
+ for json_file in Path(locales_dir).glob('**/*.json'):
41
+ locale_name = json_file.parent.name
42
+
43
+ with open(json_file, 'r', encoding='utf-8') as f:
44
+ data = json.load(f)
45
+
46
+ catalog.setdefault(locale_name, {})
47
+
48
+ if isinstance(data, dict):
49
+ for v in data.values():
50
+ if isinstance(v, dict):
51
+ catalog[locale_name].update(v)
52
+
53
+ for k, v in data.items():
54
+ if isinstance(v, str):
55
+ catalog[locale_name][k] = v
56
+
57
+ return I18n(catalog, lang)
@@ -0,0 +1,45 @@
1
+ import logging
2
+ from datetime import datetime as dt
3
+ from logging.handlers import TimedRotatingFileHandler
4
+ from pathlib import Path
5
+
6
+
7
+ def configure_logger(
8
+ name: str = 'big_views',
9
+ log_dir: str | Path = './logs',
10
+ level: int = logging.INFO,
11
+ console: bool = True,
12
+ rotating_file: bool = True,
13
+ ) -> logging.Logger:
14
+ logger = logging.getLogger(name)
15
+ logger.setLevel(level)
16
+ logger.propagate = False
17
+
18
+ log_dir = Path(log_dir)
19
+ log_dir.mkdir(parents=True, exist_ok=True)
20
+
21
+ fmt = logging.Formatter('%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s')
22
+
23
+ if rotating_file:
24
+ log_name = dt.now().strftime('%d-%m-%Y_%Hh-%Mm-%Ss')
25
+ log_path = log_dir / f'{log_name}.log'
26
+
27
+ file_handler = TimedRotatingFileHandler(
28
+ filename=str(log_path),
29
+ when='midnight',
30
+ interval=1,
31
+ backupCount=7,
32
+ encoding='utf-8',
33
+ )
34
+ file_handler.suffix = '%Y%m%d'
35
+ file_handler.setLevel(level)
36
+ file_handler.setFormatter(fmt)
37
+ logger.addHandler(file_handler)
38
+
39
+ if console:
40
+ console_handler = logging.StreamHandler()
41
+ console_handler.setLevel(level)
42
+ console_handler.setFormatter(fmt)
43
+ logger.addHandler(console_handler)
44
+
45
+ return logger