pyautoscene 0.1.0__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.
@@ -0,0 +1,12 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ explore/
@@ -0,0 +1,9 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ # Ruff version.
4
+ rev: v0.11.13
5
+ hooks:
6
+ - id: ruff-check
7
+ args: ["--extend-select", "I", "--fix"]
8
+ - id: ruff-format
9
+ args: ["--preview"]
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,200 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyautoscene
3
+ Version: 0.1.0
4
+ Summary: Advance GUI automation
5
+ Author-email: pritam-dey3 <pritam.pritamdey.984@gmail.com>
6
+ Requires-Python: >=3.13
7
+ Requires-Dist: networkx>=3.5
8
+ Requires-Dist: onnxruntime>=1.22.0
9
+ Requires-Dist: pillow>=11.3.0
10
+ Requires-Dist: pyautogui>=0.9.54
11
+ Requires-Dist: python-statemachine[diagrams]
12
+ Requires-Dist: rapidocr>=3.2.0
13
+ Description-Content-Type: text/markdown
14
+
15
+ # PyAutoScene
16
+
17
+ **Advanced GUI Automation with Scene-Based State Management**
18
+
19
+ PyAutoScene is a Python library that provides a declarative approach to GUI automation by modeling application interfaces as scenes and transitions. It combines element detection with state machine patterns to create robust, maintainable automation scripts.
20
+
21
+ ## 🌟 Features
22
+
23
+ - **Scene-Based Architecture**: Model your application as a collection of scenes with defined elements and transitions
24
+ - **Visual Element Detection**: Supports both image-based element recognition. (Text recognition support coming soon!)
25
+ - **Automatic Navigation**: Intelligent pathfinding between scenes using graph algorithms
26
+ - **Action Decorators**: Clean, declarative syntax for defining scene actions and transitions
27
+
28
+ ## 🚀 Quick Start
29
+
30
+ ### Installation
31
+
32
+ ```bash
33
+ pip install pyautoscene
34
+ ```
35
+
36
+ ### Basic Example
37
+
38
+ Here's how to automate a simple login flow:
39
+
40
+ ```python
41
+ import pyautogui as gui
42
+ from pyautoscene import ReferenceImage, ReferenceText, Scene, Session
43
+ from pyautoscene.utils import locate_and_click
44
+
45
+ # Define scenes
46
+ login = Scene(
47
+ "Login",
48
+ elements=[
49
+ ReferenceText("Welcome to Login"),
50
+ ReferenceImage("references/login_button.png"),
51
+ ],
52
+ initial=True,
53
+ )
54
+
55
+ dashboard = Scene(
56
+ "Dashboard",
57
+ elements=[
58
+ ReferenceText("Dashboard"),
59
+ ReferenceImage("references/user_menu.png"),
60
+ ],
61
+ )
62
+
63
+ # Define actions with transitions
64
+ @login.action(transitions_to=dashboard)
65
+ def perform_login(username: str, password: str):
66
+ """Performs login and transitions to dashboard."""
67
+ locate_and_click("references/username_field.png")
68
+ gui.write(username, interval=0.1)
69
+ gui.press("tab")
70
+ gui.write(password, interval=0.1)
71
+ gui.press("enter")
72
+
73
+ # Create session and navigate
74
+ session = Session(scenes=[login, dashboard])
75
+ session.expect(dashboard, username="user", password="pass")
76
+ ```
77
+
78
+ ## 📖 Core Concepts
79
+
80
+ ### Scenes
81
+
82
+ A **Scene** represents a distinct state in your application's UI. Each scene contains:
83
+
84
+ - **Elements**: Visual markers that identify when the scene is active
85
+ - **Actions**: Functions that can be performed in this scene
86
+ - **Transitions**: Connections to other scenes
87
+
88
+ ```python
89
+ scene = Scene(
90
+ "SceneName",
91
+ elements=[
92
+ ReferenceImage("path/to/image.png"),
93
+ ReferenceText("Expected Text"),
94
+ ],
95
+ initial=False # Set to True for starting scene
96
+ )
97
+ ```
98
+
99
+ ### Reference Elements
100
+
101
+ PyAutoScene supports two types of reference elements:
102
+
103
+ #### ReferenceImage
104
+
105
+ Detects scenes using image matching:
106
+
107
+ ```python
108
+ ReferenceImage("path/to/reference/image.png")
109
+ ```
110
+
111
+ #### ReferenceText
112
+ (Coming soon)
113
+ Detects scenes using text recognition:
114
+
115
+ ```python
116
+ ReferenceText("Expected text on screen")
117
+ ```
118
+
119
+ ### Actions and Transitions
120
+
121
+ Actions are decorated functions that define what can be done in a scene:
122
+
123
+ ```python
124
+ @scene.action(transitions_to=target_scene) # Action that changes scenes
125
+ def action_with_transition():
126
+ # Perform GUI operations
127
+ pass
128
+
129
+ @scene.action() # Action that stays in current scene
130
+ def action_without_transition():
131
+ # Perform GUI operations
132
+ pass
133
+ ```
134
+
135
+ ### Session Management
136
+
137
+ The **Session** class manages the state machine and provides navigation:
138
+
139
+ ```python
140
+ session = Session(scenes=[scene1, scene2, scene3])
141
+
142
+ # Navigate to a specific scene (finds optimal path)
143
+ session.expect(target_scene, **action_params)
144
+
145
+ # Invoke an action in the current scene
146
+ session.invoke("action_name", **action_params)
147
+
148
+ # Get current scene
149
+ current = session.current_scene
150
+ ```
151
+
152
+ ### Automatic Scene Detection
153
+
154
+ PyAutoScene automatically detects which scene is currently active:
155
+
156
+ ```python
157
+ from pyautoscene.session import get_current_scene
158
+
159
+ current_scene = get_current_scene(scenes)
160
+ print(f"Currently on: {current_scene.name}")
161
+ ```
162
+
163
+ ### Path Finding
164
+
165
+ The library uses NetworkX to find optimal paths between scenes:
166
+
167
+ ```python
168
+ # This will automatically navigate: Login → Dashboard → Cart
169
+ session.expect(cart_scene, username="user", password="pass")
170
+ ```
171
+
172
+ ### Error Handling
173
+
174
+ ```python
175
+ from pyautoscene.session import SceneRecognitionError
176
+
177
+ try:
178
+ session.expect(target_scene)
179
+ except SceneRecognitionError as e:
180
+ print(f"Navigation failed: {e}")
181
+ ```
182
+
183
+ ## 🤝 Contributing
184
+
185
+ 1. Fork the repository
186
+ 2. Create a feature branch: `git checkout -b feature-name`
187
+ 3. Make your changes and add tests
188
+ 4. Run pre-commit hooks: `pre-commit run --all-files`
189
+ 5. Submit a pull request
190
+
191
+ ## 📝 License
192
+
193
+ This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
194
+
195
+ ## 🔮 Roadmap
196
+
197
+ - [ ] Text recognition implementation
198
+ - [ ] Enhanced image matching algorithms
199
+ - [ ] Multiple session support
200
+
@@ -0,0 +1,186 @@
1
+ # PyAutoScene
2
+
3
+ **Advanced GUI Automation with Scene-Based State Management**
4
+
5
+ PyAutoScene is a Python library that provides a declarative approach to GUI automation by modeling application interfaces as scenes and transitions. It combines element detection with state machine patterns to create robust, maintainable automation scripts.
6
+
7
+ ## 🌟 Features
8
+
9
+ - **Scene-Based Architecture**: Model your application as a collection of scenes with defined elements and transitions
10
+ - **Visual Element Detection**: Supports both image-based element recognition. (Text recognition support coming soon!)
11
+ - **Automatic Navigation**: Intelligent pathfinding between scenes using graph algorithms
12
+ - **Action Decorators**: Clean, declarative syntax for defining scene actions and transitions
13
+
14
+ ## 🚀 Quick Start
15
+
16
+ ### Installation
17
+
18
+ ```bash
19
+ pip install pyautoscene
20
+ ```
21
+
22
+ ### Basic Example
23
+
24
+ Here's how to automate a simple login flow:
25
+
26
+ ```python
27
+ import pyautogui as gui
28
+ from pyautoscene import ReferenceImage, ReferenceText, Scene, Session
29
+ from pyautoscene.utils import locate_and_click
30
+
31
+ # Define scenes
32
+ login = Scene(
33
+ "Login",
34
+ elements=[
35
+ ReferenceText("Welcome to Login"),
36
+ ReferenceImage("references/login_button.png"),
37
+ ],
38
+ initial=True,
39
+ )
40
+
41
+ dashboard = Scene(
42
+ "Dashboard",
43
+ elements=[
44
+ ReferenceText("Dashboard"),
45
+ ReferenceImage("references/user_menu.png"),
46
+ ],
47
+ )
48
+
49
+ # Define actions with transitions
50
+ @login.action(transitions_to=dashboard)
51
+ def perform_login(username: str, password: str):
52
+ """Performs login and transitions to dashboard."""
53
+ locate_and_click("references/username_field.png")
54
+ gui.write(username, interval=0.1)
55
+ gui.press("tab")
56
+ gui.write(password, interval=0.1)
57
+ gui.press("enter")
58
+
59
+ # Create session and navigate
60
+ session = Session(scenes=[login, dashboard])
61
+ session.expect(dashboard, username="user", password="pass")
62
+ ```
63
+
64
+ ## 📖 Core Concepts
65
+
66
+ ### Scenes
67
+
68
+ A **Scene** represents a distinct state in your application's UI. Each scene contains:
69
+
70
+ - **Elements**: Visual markers that identify when the scene is active
71
+ - **Actions**: Functions that can be performed in this scene
72
+ - **Transitions**: Connections to other scenes
73
+
74
+ ```python
75
+ scene = Scene(
76
+ "SceneName",
77
+ elements=[
78
+ ReferenceImage("path/to/image.png"),
79
+ ReferenceText("Expected Text"),
80
+ ],
81
+ initial=False # Set to True for starting scene
82
+ )
83
+ ```
84
+
85
+ ### Reference Elements
86
+
87
+ PyAutoScene supports two types of reference elements:
88
+
89
+ #### ReferenceImage
90
+
91
+ Detects scenes using image matching:
92
+
93
+ ```python
94
+ ReferenceImage("path/to/reference/image.png")
95
+ ```
96
+
97
+ #### ReferenceText
98
+ (Coming soon)
99
+ Detects scenes using text recognition:
100
+
101
+ ```python
102
+ ReferenceText("Expected text on screen")
103
+ ```
104
+
105
+ ### Actions and Transitions
106
+
107
+ Actions are decorated functions that define what can be done in a scene:
108
+
109
+ ```python
110
+ @scene.action(transitions_to=target_scene) # Action that changes scenes
111
+ def action_with_transition():
112
+ # Perform GUI operations
113
+ pass
114
+
115
+ @scene.action() # Action that stays in current scene
116
+ def action_without_transition():
117
+ # Perform GUI operations
118
+ pass
119
+ ```
120
+
121
+ ### Session Management
122
+
123
+ The **Session** class manages the state machine and provides navigation:
124
+
125
+ ```python
126
+ session = Session(scenes=[scene1, scene2, scene3])
127
+
128
+ # Navigate to a specific scene (finds optimal path)
129
+ session.expect(target_scene, **action_params)
130
+
131
+ # Invoke an action in the current scene
132
+ session.invoke("action_name", **action_params)
133
+
134
+ # Get current scene
135
+ current = session.current_scene
136
+ ```
137
+
138
+ ### Automatic Scene Detection
139
+
140
+ PyAutoScene automatically detects which scene is currently active:
141
+
142
+ ```python
143
+ from pyautoscene.session import get_current_scene
144
+
145
+ current_scene = get_current_scene(scenes)
146
+ print(f"Currently on: {current_scene.name}")
147
+ ```
148
+
149
+ ### Path Finding
150
+
151
+ The library uses NetworkX to find optimal paths between scenes:
152
+
153
+ ```python
154
+ # This will automatically navigate: Login → Dashboard → Cart
155
+ session.expect(cart_scene, username="user", password="pass")
156
+ ```
157
+
158
+ ### Error Handling
159
+
160
+ ```python
161
+ from pyautoscene.session import SceneRecognitionError
162
+
163
+ try:
164
+ session.expect(target_scene)
165
+ except SceneRecognitionError as e:
166
+ print(f"Navigation failed: {e}")
167
+ ```
168
+
169
+ ## 🤝 Contributing
170
+
171
+ 1. Fork the repository
172
+ 2. Create a feature branch: `git checkout -b feature-name`
173
+ 3. Make your changes and add tests
174
+ 4. Run pre-commit hooks: `pre-commit run --all-files`
175
+ 5. Submit a pull request
176
+
177
+ ## 📝 License
178
+
179
+ This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
180
+
181
+ ## 🔮 Roadmap
182
+
183
+ - [ ] Text recognition implementation
184
+ - [ ] Enhanced image matching algorithms
185
+ - [ ] Multiple session support
186
+
@@ -0,0 +1,68 @@
1
+ import pyautogui as gui
2
+
3
+ from pyautoscene import ReferenceImage, ReferenceText, Scene, Session
4
+ from pyautoscene.utils import locate_and_click
5
+
6
+ login = Scene(
7
+ "Login",
8
+ elements=[
9
+ ReferenceText("Welcome to Login"),
10
+ ReferenceImage("examples/saucedemo/references/login_button.png"),
11
+ ],
12
+ initial=True,
13
+ )
14
+
15
+ dashboard = Scene(
16
+ "Dashboard",
17
+ elements=[
18
+ ReferenceText("Swag Labs"),
19
+ ReferenceText("Products"),
20
+ ReferenceImage("examples/saucedemo/references/cart_icon.png"),
21
+ ],
22
+ )
23
+
24
+ cart = Scene(
25
+ "Cart",
26
+ elements=[
27
+ ReferenceText("Your Cart"),
28
+ ReferenceImage("examples/saucedemo/references/cart_icon.png"),
29
+ ],
30
+ )
31
+
32
+
33
+ @login.action(transitions_to=dashboard)
34
+ def perform_login(username: str, password: str):
35
+ """Performs the login action to transition from Login to Dashboard."""
36
+ locate_and_click("examples/saucedemo/references/username.png")
37
+ gui.write(username, interval=0.1)
38
+ gui.press("tab")
39
+ gui.write(password, interval=0.1)
40
+ gui.press("enter")
41
+
42
+
43
+ @dashboard.action()
44
+ def add_products_to_cart(target: str):
45
+ """Adds products to the cart."""
46
+ locate_and_click(f"examples/saucedemo/references/{target}.png")
47
+ locate_and_click("examples/saucedemo/references/add_to_cart_button.png")
48
+
49
+
50
+ @dashboard.action(transitions_to=cart)
51
+ def view_cart():
52
+ """Views the cart."""
53
+ locate_and_click("examples/saucedemo/references/cart_icon.png")
54
+
55
+
56
+ @cart.action()
57
+ def checkout():
58
+ """Checks out the items in the cart."""
59
+ locate_and_click("examples/saucedemo/references/checkout_button.png")
60
+
61
+
62
+ session = Session(scenes=[login, dashboard, cart])
63
+
64
+ gui.hotkey("alt", "tab")
65
+ session.expect(dashboard, username="standard_user", password="secret_sauce")
66
+ session.invoke("add_products_to_cart", target="backpack")
67
+ session.invoke("view_cart")
68
+ session.invoke("checkout")
@@ -0,0 +1,72 @@
1
+ import pyautogui as gui
2
+
3
+ from pyautoscene import ReferenceImage, ReferenceText, Scene, Session
4
+ from pyautoscene.utils import locate_and_click
5
+
6
+ login = Scene(
7
+ "Login",
8
+ elements=[
9
+ ReferenceText("Welcome to Login"),
10
+ ReferenceImage("examples/saucedemo/references/login_button.png"),
11
+ ],
12
+ initial=True,
13
+ )
14
+
15
+ dashboard = Scene(
16
+ "Dashboard",
17
+ elements=[
18
+ ReferenceText("Swag Labs"),
19
+ ReferenceText("Products"),
20
+ ReferenceImage("examples/saucedemo/references/cart_icon.png"),
21
+ ],
22
+ )
23
+
24
+ cart = Scene(
25
+ "Cart",
26
+ elements=[
27
+ ReferenceText("Your Cart"),
28
+ ReferenceImage("examples/saucedemo/references/cart_icon.png"),
29
+ ],
30
+ )
31
+
32
+
33
+ @login.action(transitions_to=dashboard)
34
+ def perform_login(username: str, password: str):
35
+ """Performs the login action to transition from Login to Dashboard."""
36
+ locate_and_click("examples/saucedemo/references/username.png")
37
+ gui.write(username, interval=0.1)
38
+ gui.press("tab")
39
+ gui.write(password, interval=0.1)
40
+ gui.press("enter")
41
+
42
+
43
+ @dashboard.action()
44
+ def add_products_to_cart(target: str):
45
+ """Adds products to the cart."""
46
+ locate_and_click(f"examples/saucedemo/references/{target}.png")
47
+ locate_and_click("examples/saucedemo/references/add_to_cart_button.png")
48
+
49
+
50
+ @dashboard.action(transitions_to=cart)
51
+ def view_cart():
52
+ """Views the cart."""
53
+ locate_and_click("examples/saucedemo/references/cart_icon.png")
54
+
55
+
56
+ @cart.action()
57
+ def checkout():
58
+ """Checks out the items in the cart."""
59
+ locate_and_click("examples/saucedemo/references/checkout_button.png")
60
+
61
+
62
+ session = Session(scenes=[login, dashboard, cart])
63
+
64
+ # test internal state machine
65
+ gui.hotkey("alt", "tab")
66
+ print(f"{session.current_scene=}")
67
+ session.invoke("perform_login", username="standard_user", password="secret_sauce")
68
+ print(f"After login: {session._sm.current_state=}")
69
+ session.invoke("add_products_to_cart", target="backpack")
70
+ session.invoke("view_cart")
71
+ print(f"After adding to cart: {session._sm.current_state=}")
72
+ session.invoke("checkout")
@@ -0,0 +1,36 @@
1
+ [project]
2
+ authors = [
3
+ {name = "pritam-dey3", email = "pritam.pritamdey.984@gmail.com"},
4
+ ]
5
+ dependencies = [
6
+ "networkx>=3.5",
7
+ "onnxruntime>=1.22.0",
8
+ "pillow>=11.3.0",
9
+ "pyautogui>=0.9.54",
10
+ "python-statemachine[diagrams]",
11
+ "rapidocr>=3.2.0",
12
+ ]
13
+ description = "Advance GUI automation"
14
+ name = "pyautoscene"
15
+ readme = "README.md"
16
+ requires-python = ">=3.13"
17
+ version = "0.1.0"
18
+
19
+ [project.scripts]
20
+ pyautoscene = "pyautoscene:main"
21
+
22
+ [build-system]
23
+ build-backend = "hatchling.build"
24
+ requires = ["hatchling"]
25
+
26
+ [tool.uv.sources]
27
+ python-statemachine = {git = "https://github.com/fgmacedo/python-statemachine.git", rev = "9a089edf61b4afd4abc08968b3cfa508fa332f7c"}
28
+
29
+ [dependency-groups]
30
+ dev = [
31
+ "pre-commit>=4.2.0",
32
+ "types-networkx>=3.5.0.20250712",
33
+ ]
34
+
35
+ [tool.poe.tasks]
36
+ precmt = "pre-commit run --all-files"
@@ -0,0 +1,5 @@
1
+ from .references import ReferenceImage, ReferenceText
2
+ from .scene import Scene
3
+ from .session import Session
4
+
5
+ __all__ = ["Scene", "Session", "ReferenceImage", "ReferenceText"]
@@ -0,0 +1,38 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ import pyautogui as gui
4
+ from pyscreeze import Box
5
+
6
+
7
+ class ReferenceElement(ABC):
8
+ """Base class for reference elements used to identify scenes."""
9
+
10
+ @abstractmethod
11
+ def is_visible(self):
12
+ """Detect the presence of the reference element."""
13
+ raise NotImplementedError("Subclasses must implement this method")
14
+
15
+
16
+ class ReferenceImage(ReferenceElement):
17
+ """Reference element that identifies a scene by an image."""
18
+
19
+ def __init__(self, image_path: str):
20
+ self.image_path = image_path
21
+
22
+ def is_visible(self, region: Box | None = None):
23
+ """Method to detect the presence of the image in the current screen."""
24
+ try:
25
+ return gui.locateOnScreen(self.image_path, region=region)
26
+ except gui.ImageNotFoundException:
27
+ return None
28
+
29
+
30
+ class ReferenceText(ReferenceElement):
31
+ """Reference element that identifies a scene by text."""
32
+
33
+ def __init__(self, text: str):
34
+ self.text = text
35
+
36
+ def is_visible(self):
37
+ """Method to detect the presence of the text in the current screen."""
38
+ raise NotImplementedError("Text recognition is not implemented yet.")