portacode 0.3.16.dev10__py3-none-any.whl → 1.4.11.dev1__py3-none-any.whl

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.

Potentially problematic release.


This version of portacode might be problematic. Click here for more details.

Files changed (92) hide show
  1. portacode/_version.py +16 -3
  2. portacode/cli.py +143 -17
  3. portacode/connection/client.py +149 -10
  4. portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +928 -42
  5. portacode/connection/handlers/__init__.py +34 -5
  6. portacode/connection/handlers/base.py +78 -16
  7. portacode/connection/handlers/chunked_content.py +244 -0
  8. portacode/connection/handlers/diff_handlers.py +603 -0
  9. portacode/connection/handlers/file_handlers.py +902 -17
  10. portacode/connection/handlers/project_aware_file_handlers.py +226 -0
  11. portacode/connection/handlers/project_state/README.md +312 -0
  12. portacode/connection/handlers/project_state/__init__.py +92 -0
  13. portacode/connection/handlers/project_state/file_system_watcher.py +179 -0
  14. portacode/connection/handlers/project_state/git_manager.py +1502 -0
  15. portacode/connection/handlers/project_state/handlers.py +875 -0
  16. portacode/connection/handlers/project_state/manager.py +1331 -0
  17. portacode/connection/handlers/project_state/models.py +108 -0
  18. portacode/connection/handlers/project_state/utils.py +50 -0
  19. portacode/connection/handlers/project_state_handlers.py +45 -948
  20. portacode/connection/handlers/proxmox_infra.py +361 -0
  21. portacode/connection/handlers/registry.py +15 -4
  22. portacode/connection/handlers/session.py +483 -32
  23. portacode/connection/handlers/system_handlers.py +147 -8
  24. portacode/connection/handlers/tab_factory.py +389 -0
  25. portacode/connection/handlers/terminal_handlers.py +21 -8
  26. portacode/connection/handlers/update_handler.py +61 -0
  27. portacode/connection/multiplex.py +60 -2
  28. portacode/connection/terminal.py +256 -17
  29. portacode/keypair.py +63 -1
  30. portacode/link_capture/__init__.py +38 -0
  31. portacode/link_capture/__pycache__/__init__.cpython-311.pyc +0 -0
  32. portacode/link_capture/bin/__pycache__/link_capture_wrapper.cpython-311.pyc +0 -0
  33. portacode/link_capture/bin/elinks +3 -0
  34. portacode/link_capture/bin/gio-open +3 -0
  35. portacode/link_capture/bin/gnome-open +3 -0
  36. portacode/link_capture/bin/gvfs-open +3 -0
  37. portacode/link_capture/bin/kde-open +3 -0
  38. portacode/link_capture/bin/kfmclient +3 -0
  39. portacode/link_capture/bin/link_capture_exec.sh +11 -0
  40. portacode/link_capture/bin/link_capture_wrapper.py +75 -0
  41. portacode/link_capture/bin/links +3 -0
  42. portacode/link_capture/bin/links2 +3 -0
  43. portacode/link_capture/bin/lynx +3 -0
  44. portacode/link_capture/bin/mate-open +3 -0
  45. portacode/link_capture/bin/netsurf +3 -0
  46. portacode/link_capture/bin/sensible-browser +3 -0
  47. portacode/link_capture/bin/w3m +3 -0
  48. portacode/link_capture/bin/x-www-browser +3 -0
  49. portacode/link_capture/bin/xdg-open +3 -0
  50. portacode/logging_categories.py +140 -0
  51. portacode/pairing.py +103 -0
  52. portacode/static/js/test-ntp-clock.html +63 -0
  53. portacode/static/js/utils/ntp-clock.js +232 -0
  54. portacode/utils/NTP_ARCHITECTURE.md +136 -0
  55. portacode/utils/__init__.py +1 -0
  56. portacode/utils/diff_apply.py +456 -0
  57. portacode/utils/diff_renderer.py +371 -0
  58. portacode/utils/ntp_clock.py +65 -0
  59. portacode-1.4.11.dev1.dist-info/METADATA +298 -0
  60. portacode-1.4.11.dev1.dist-info/RECORD +97 -0
  61. {portacode-0.3.16.dev10.dist-info → portacode-1.4.11.dev1.dist-info}/WHEEL +1 -1
  62. portacode-1.4.11.dev1.dist-info/top_level.txt +3 -0
  63. test_modules/README.md +296 -0
  64. test_modules/__init__.py +1 -0
  65. test_modules/test_device_online.py +44 -0
  66. test_modules/test_file_operations.py +743 -0
  67. test_modules/test_git_status_ui.py +370 -0
  68. test_modules/test_login_flow.py +50 -0
  69. test_modules/test_navigate_testing_folder.py +361 -0
  70. test_modules/test_play_store_screenshots.py +294 -0
  71. test_modules/test_terminal_buffer_performance.py +261 -0
  72. test_modules/test_terminal_interaction.py +80 -0
  73. test_modules/test_terminal_loading_race_condition.py +95 -0
  74. test_modules/test_terminal_start.py +56 -0
  75. testing_framework/.env.example +21 -0
  76. testing_framework/README.md +334 -0
  77. testing_framework/__init__.py +17 -0
  78. testing_framework/cli.py +326 -0
  79. testing_framework/core/__init__.py +1 -0
  80. testing_framework/core/base_test.py +336 -0
  81. testing_framework/core/cli_manager.py +177 -0
  82. testing_framework/core/hierarchical_runner.py +577 -0
  83. testing_framework/core/playwright_manager.py +520 -0
  84. testing_framework/core/runner.py +447 -0
  85. testing_framework/core/shared_cli_manager.py +234 -0
  86. testing_framework/core/test_discovery.py +112 -0
  87. testing_framework/requirements.txt +12 -0
  88. portacode-0.3.16.dev10.dist-info/METADATA +0 -238
  89. portacode-0.3.16.dev10.dist-info/RECORD +0 -29
  90. portacode-0.3.16.dev10.dist-info/top_level.txt +0 -1
  91. {portacode-0.3.16.dev10.dist-info → portacode-1.4.11.dev1.dist-info}/entry_points.txt +0 -0
  92. {portacode-0.3.16.dev10.dist-info → portacode-1.4.11.dev1.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,112 @@
1
+ """Test discovery and categorization system."""
2
+
3
+ import os
4
+ import importlib.util
5
+ import inspect
6
+ from pathlib import Path
7
+ from typing import List, Dict, Any, Optional, Set
8
+ import logging
9
+
10
+ from .base_test import BaseTest, TestCategory
11
+
12
+
13
+ class TestDiscovery:
14
+ """Discovers and categorizes tests from the filesystem."""
15
+
16
+ def __init__(self, test_directories: Optional[List[str]] = None):
17
+ self.test_directories = test_directories or ["tests", "test_modules"]
18
+ self.logger = logging.getLogger("test_discovery")
19
+ self.logger.setLevel(logging.ERROR) # Show errors during discovery
20
+ self.discovered_tests: Dict[str, BaseTest] = {}
21
+
22
+ def discover_tests(self, base_path: str = ".") -> Dict[str, BaseTest]:
23
+ """Discover all test classes in the specified directories."""
24
+ base_path = Path(base_path)
25
+ self.discovered_tests = {}
26
+
27
+ for test_dir in self.test_directories:
28
+ test_path = base_path / test_dir
29
+ if test_path.exists() and test_path.is_dir():
30
+ self.logger.info(f"Discovering tests in: {test_path}")
31
+ self._discover_in_directory(test_path)
32
+
33
+ self.logger.info(f"Discovered {len(self.discovered_tests)} tests")
34
+ return self.discovered_tests
35
+
36
+ def _discover_in_directory(self, directory: Path):
37
+ """Recursively discover tests in a directory."""
38
+ for item in directory.rglob("*.py"):
39
+ if item.name.startswith("test_") or item.name.endswith("_test.py"):
40
+ self._discover_in_file(item)
41
+
42
+ def _discover_in_file(self, file_path: Path):
43
+ """Discover test classes in a Python file."""
44
+ try:
45
+ # Load the module
46
+ spec = importlib.util.spec_from_file_location("test_module", file_path)
47
+ if spec and spec.loader:
48
+ module = importlib.util.module_from_spec(spec)
49
+ spec.loader.exec_module(module)
50
+
51
+ # Find test classes
52
+ for name, obj in inspect.getmembers(module):
53
+ if (inspect.isclass(obj) and
54
+ issubclass(obj, BaseTest) and
55
+ obj is not BaseTest):
56
+
57
+ # Instantiate the test class
58
+ try:
59
+ test_instance = obj()
60
+ self.discovered_tests[test_instance.name] = test_instance
61
+ self.logger.debug(f"Discovered test: {test_instance.name}")
62
+ except Exception as e:
63
+ error_msg = f"Failed to instantiate test {name} in {file_path}: {e}"
64
+ self.logger.error(error_msg)
65
+ print(f"❌ {error_msg}") # Also print to console for immediate visibility
66
+
67
+ except Exception as e:
68
+ error_msg = f"Failed to load test file {file_path}: {e}"
69
+ self.logger.error(error_msg)
70
+ print(f"❌ {error_msg}") # Also print to console for immediate visibility
71
+
72
+ def get_tests_by_category(self, category: TestCategory) -> List[BaseTest]:
73
+ """Get all tests belonging to a specific category."""
74
+ return [test for test in self.discovered_tests.values()
75
+ if test.category == category]
76
+
77
+ def get_tests_by_tags(self, tags: Set[str]) -> List[BaseTest]:
78
+ """Get all tests that have any of the specified tags."""
79
+ return [test for test in self.discovered_tests.values()
80
+ if any(tag in test.tags for tag in tags)]
81
+
82
+ def get_tests_by_name_pattern(self, pattern: str) -> List[BaseTest]:
83
+ """Get all tests whose names match the pattern."""
84
+ import re
85
+ regex = re.compile(pattern, re.IGNORECASE)
86
+ return [test for test in self.discovered_tests.values()
87
+ if regex.search(test.name)]
88
+
89
+ def list_all_categories(self) -> Set[TestCategory]:
90
+ """Get all categories found in discovered tests."""
91
+ return {test.category for test in self.discovered_tests.values()}
92
+
93
+ def list_all_tags(self) -> Set[str]:
94
+ """Get all tags found in discovered tests."""
95
+ all_tags = set()
96
+ for test in self.discovered_tests.values():
97
+ all_tags.update(test.tags)
98
+ return all_tags
99
+
100
+ def get_test_info(self) -> Dict[str, Dict[str, Any]]:
101
+ """Get detailed information about all discovered tests."""
102
+ info = {}
103
+ for name, test in self.discovered_tests.items():
104
+ info[name] = {
105
+ "name": test.name,
106
+ "category": test.category.value,
107
+ "description": test.description,
108
+ "tags": test.tags,
109
+ "class_name": test.__class__.__name__,
110
+ "module": test.__class__.__module__
111
+ }
112
+ return info
@@ -0,0 +1,12 @@
1
+ # Testing Framework Dependencies
2
+
3
+ # Core testing framework dependencies
4
+ playwright>=1.40.0
5
+ click>=8.1.0
6
+
7
+ # Optional: For environment variable management
8
+ python-dotenv>=1.0.0
9
+
10
+ # Development dependencies (optional)
11
+ pytest>=7.0.0
12
+ pytest-asyncio>=0.21.0
@@ -1,238 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: portacode
3
- Version: 0.3.16.dev10
4
- Summary: Portacode CLI client and SDK
5
- Home-page: https://github.com/portacode/portacode
6
- Author: Meena Erian
7
- Author-email: hi@menas.pro
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.8
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: click>=8.0
15
- Requires-Dist: platformdirs>=3.0
16
- Requires-Dist: cryptography>=41.0
17
- Requires-Dist: websockets>=12.0
18
- Requires-Dist: pyperclip>=1.8
19
- Requires-Dist: psutil>=5.9
20
- Requires-Dist: pyte>=0.8
21
- Requires-Dist: GitPython>=3.1.45
22
- Requires-Dist: pywinpty>=2.0; platform_system == "Windows"
23
- Provides-Extra: dev
24
- Requires-Dist: black; extra == "dev"
25
- Requires-Dist: flake8; extra == "dev"
26
- Requires-Dist: pytest; extra == "dev"
27
-
28
- # Portacode
29
-
30
- **An AI-first, mobile-first IDE and admin tool, made with love and passion by software engineers, for software engineers.**
31
-
32
- Portacode transforms any computer into a remotely accessible development environment. Access your home lab from your phone, code on your desktop from anywhere, or help a colleague debug their server - all through a beautiful web interface designed for the modern developer.
33
-
34
- ## ✨ Why Portacode?
35
-
36
- - **🤖 AI-First**: Built from the ground up with AI integration in mind
37
- - **📱 Mobile-First**: Code and administrate from your phone or tablet
38
- - **🌍 Global Access**: Connect to your devices from anywhere with internet
39
- - **🔐 Secure**: HTTPS encrypted with RSA key authentication
40
- - **⚡ Fast Setup**: Get connected in under 60 seconds
41
- - **🔄 Always Connected**: Automatic reconnection and persistent service options
42
- - **🆓 Free Account**: Create your account and start connecting immediately
43
- - **🖥️ Cross-Platform**: Works on Windows, macOS, and Linux
44
-
45
- ## 🚀 Quick Start
46
-
47
- ### 1. Install Portacode
48
-
49
- ```bash
50
- pip install portacode
51
- ```
52
-
53
- ### 2. Connect Your Device
54
-
55
- ```bash
56
- portacode connect
57
- ```
58
-
59
- Follow the on-screen instructions to:
60
- - Visit [https://remote.portacode.com](https://remote.portacode.com)
61
- - Create your free account
62
- - Add your device using the generated key
63
- - Start coding and administrating!
64
-
65
- ### 3. Access Your Development Environment
66
-
67
- Once connected, you can:
68
- - Open terminal sessions from the web dashboard
69
- - Execute commands remotely
70
- - Monitor system status
71
- - Access your development environment from any device
72
-
73
- ## 💡 Use Cases
74
-
75
- ### Remote Development
76
- ```bash
77
- # Connect your development machine
78
- portacode connect
79
-
80
- # Now code, build, and debug from anywhere - even your phone
81
- ```
82
-
83
- ### Server Administration
84
- ```bash
85
- # For a persistent connection, install system-wide first
86
- sudo pip install portacode --system
87
-
88
- # Then install as a service
89
- sudo portacode service install
90
-
91
- # Your server is now accessible 24/7 from the web dashboard
92
- ```
93
-
94
- ### Mobile Development
95
- ```bash
96
- # Connect your desktop/laptop
97
- portacode connect
98
-
99
- # Code on-the-go from your mobile device with a full IDE experience
100
- ```
101
-
102
- ### Team Collaboration
103
- ```bash
104
- # Connect shared development environments
105
- portacode connect
106
-
107
- # Enable team members to access shared resources securely
108
- ```
109
-
110
- ## 🔧 Essential Commands
111
-
112
- ### Basic Usage
113
- ```bash
114
- # Start a connection (runs until closed)
115
- portacode connect
116
-
117
- # Run connection in background
118
- portacode connect --detach
119
-
120
- # Check version
121
- portacode --version
122
-
123
- # Get help
124
- portacode --help
125
- ```
126
-
127
- ### Service Management
128
- ```bash
129
- # For system services, install package system-wide first
130
- sudo pip install portacode --system
131
-
132
- # Install persistent service (auto-start on boot)
133
- sudo portacode service install
134
-
135
- # Check service status
136
- sudo portacode service status
137
-
138
- # Stop the service
139
- sudo portacode service stop
140
-
141
- # Remove the service
142
- sudo portacode service uninstall
143
- ```
144
-
145
- ## 🌐 Web Dashboard
146
-
147
- Access your connected devices at [https://remote.portacode.com](https://remote.portacode.com)
148
-
149
- **Current Features:**
150
- - Real-time terminal access
151
- - System monitoring
152
- - Device management
153
- - Multi-device switching
154
- - Secure authentication
155
-
156
- **Coming Soon:**
157
- - AI-powered code assistance
158
- - Mobile-optimized IDE interface
159
- - File management and editing
160
- - Collaborative development tools
161
-
162
- ## 🔐 Security
163
-
164
- - **RSA Key Authentication**: Each device gets a unique RSA key pair
165
- - **HTTPS Encrypted**: All communication is encrypted in transit
166
- - **No Passwords**: Key-based authentication eliminates password risks
167
- - **Revocable Access**: Remove devices instantly from the web dashboard
168
- - **Local Key Storage**: Private keys never leave your device
169
-
170
- ## 🆘 Troubleshooting
171
-
172
- ### Connection Issues
173
- ```bash
174
- # Check if another connection is running
175
- portacode connect
176
-
177
- # View service logs
178
- sudo portacode service status --verbose
179
- ```
180
-
181
- ### Service Installation Issues
182
- ```bash
183
- # If service commands fail, ensure system-wide installation
184
- sudo pip install portacode --system
185
-
186
- # Then try service installation again
187
- sudo portacode service install
188
- ```
189
-
190
- ### Clipboard Issues (Linux)
191
- ```bash
192
- # Install clipboard support
193
- sudo apt-get install xclip
194
- ```
195
-
196
- ### Key Management
197
- Key files are stored in:
198
- - **Linux**: `~/.local/share/portacode/keys/`
199
- - **macOS**: `~/Library/Application Support/portacode/keys/`
200
- - **Windows**: `%APPDATA%\portacode\keys\`
201
-
202
- ## 🌱 Early Stage Project
203
-
204
- **Portacode is a young project with big dreams.** We're building the future of remote development and mobile-first coding experiences. As a new project, we're actively seeking:
205
-
206
- - **👥 Community Feedback**: Does this solve a real problem for you?
207
- - **🤝 Contributors**: Help us build the IDE of the future
208
- - **📢 Early Adopters**: Try it out and let us know what you think
209
- - **💡 Feature Ideas**: What would make your remote development workflow better?
210
-
211
- **Your support matters!** Whether you contribute code, report bugs, share ideas, or simply let us know that you find value in what we're building - every bit of feedback helps us decide whether to continue investing in this vision or focus on other projects.
212
-
213
- ## 📞 Get In Touch
214
-
215
- - **Email**: hi@menas.pro
216
- - **Support**: support@portacode.com
217
- - **GitHub**: [https://github.com/portacode/portacode](https://github.com/portacode/portacode)
218
-
219
- ## 🤝 Contributing
220
-
221
- We welcome all forms of contribution:
222
- - 🐛 **Bug Reports**: Found something broken? Let us know!
223
- - ✨ **Feature Requests**: What would make Portacode better for you?
224
- - 📖 **Documentation**: Help others get started
225
- - 💻 **Code Contributions**: Help us build the future of remote development
226
- - 💬 **Feedback**: Tell us if you find this useful!
227
-
228
- Check out our [GitHub repository](https://github.com/portacode/portacode) to get started.
229
-
230
- ## 📄 License
231
-
232
- MIT License - see [LICENSE](LICENSE) file for details.
233
-
234
- ---
235
-
236
- **Get started today**: `pip install portacode && portacode connect`
237
-
238
- *Built with ❤️ and ☕ by passionate software engineers*
@@ -1,29 +0,0 @@
1
- portacode/README.md,sha256=4dKtpvR8LNgZPVz37GmkQCMWIr_u25Ao63iW56s7Ke4,775
2
- portacode/__init__.py,sha256=oB3sV1wXr-um-RXio73UG8E5Xx6cF2ZVJveqjNmC-vQ,1086
3
- portacode/__main__.py,sha256=jmHTGC1hzmo9iKJLv-SSYe9BSIbPPZ2IOpecI03PlTs,296
4
- portacode/_version.py,sha256=JeTT_cPslV_QT36_j1radatORDpM_WFHub90EOL0kek,528
5
- portacode/cli.py,sha256=Zb2XjPsfomFsgIudYiuL2AYXqSDqmj8vJDQzsAMiyYY,15218
6
- portacode/data.py,sha256=5-s291bv8J354myaHm1Y7CQZTZyRzMU3TGe5U4hb-FA,1591
7
- portacode/keypair.py,sha256=PAcOYqlVLOoZTPYi6LvLjfsY6BkrWbLOhSZLb8r5sHs,3635
8
- portacode/service.py,sha256=p-HHMOAl20QsdcJydcZ74Iqes-wl8G8HItdSim30pUk,16537
9
- portacode/connection/README.md,sha256=f9rbuIEKa7cTm9C98rCiBbEtbiIXQU11esGSNhSMiJg,883
10
- portacode/connection/__init__.py,sha256=atqcVGkViIEd7pRa6cP2do07RJOM0UWpbnz5zXjGktU,250
11
- portacode/connection/client.py,sha256=pjAcsgPIwtvUs0AL2XiqoFeaQxQjHTvWP8cZZj8ooN4,7821
12
- portacode/connection/multiplex.py,sha256=P3jMo-Wm-RWpQ_aV1d73z8wWzjUvRfCZTmceWdkScYc,2087
13
- portacode/connection/terminal.py,sha256=n3QmF7lr5i8VxZPprSXY5WJ9y745gHv2JDxmoQC5Ads,30722
14
- portacode/connection/handlers/README.md,sha256=HsLZG1QK1JNm67HsgL6WoDg9nxzKXxwkc5fJPFJdX5g,12169
15
- portacode/connection/handlers/WEBSOCKET_PROTOCOL.md,sha256=ZC812gZBv3DtznZI1WDrAO3zyIN9GGAQr4HP2sSiXgc,33685
16
- portacode/connection/handlers/__init__.py,sha256=c2VZRFqVd7xBP4xGc8lacqGFVr-SFiUqHCh2oc-n8rM,1522
17
- portacode/connection/handlers/base.py,sha256=VCu8UO7sf_G3a-YyeE4ZTH8u83ZEcgNZY7Y7-y3Gv1M,6405
18
- portacode/connection/handlers/file_handlers.py,sha256=LQVavJTAFy9xaINRYUN5qSCiavfZf0sVhUz5ZHILju0,7095
19
- portacode/connection/handlers/project_state_handlers.py,sha256=RzKAjPBqojEZr722wS-9JwKr7Ij8tN3ebFpOd0_MZhk,38234
20
- portacode/connection/handlers/registry.py,sha256=ebi0vhR1XXSYU7mJXlQJ4MjBYaMygGYqX7ReK7vsZ7o,5558
21
- portacode/connection/handlers/session.py,sha256=_DQWAXdzhpLxl8k7LFGc9RsGNGHTJMyI73rGOzqXMjc,22574
22
- portacode/connection/handlers/system_handlers.py,sha256=65V5ctT0dIBc-oWG91e62MbdvU0z6x6JCTQuIqCWmZ0,5242
23
- portacode/connection/handlers/terminal_handlers.py,sha256=Yuo84zwKB5OiLuVtDLCQgMVrOS3T8ZOONxXpGnnougo,11019
24
- portacode-0.3.16.dev10.dist-info/LICENSE,sha256=2FGbCnUDgRYuQTkB1O1dUUpu5CVAjK1j4_p6ack9Z54,1066
25
- portacode-0.3.16.dev10.dist-info/METADATA,sha256=ZfUIrFQT_QnNssi8sXf9e2vafCinaVjgSjfbhrW0nUg,6833
26
- portacode-0.3.16.dev10.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
27
- portacode-0.3.16.dev10.dist-info/entry_points.txt,sha256=lLUUL-BM6_wwe44Xv0__5NQ1BnAz6jWjSMFvZdWW3zU,48
28
- portacode-0.3.16.dev10.dist-info/top_level.txt,sha256=U_n6hYjK7CBYFzYluuG-AP8UouIIQLCObIj6-WtG3Go,10
29
- portacode-0.3.16.dev10.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- portacode