portacode 0.3.4.dev0__py3-none-any.whl → 1.4.11.dev0__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 (93) hide show
  1. portacode/_version.py +16 -3
  2. portacode/cli.py +155 -19
  3. portacode/connection/client.py +152 -12
  4. portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +1577 -0
  5. portacode/connection/handlers/__init__.py +43 -1
  6. portacode/connection/handlers/base.py +122 -18
  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 -0
  20. portacode/connection/handlers/proxmox_infra.py +307 -0
  21. portacode/connection/handlers/registry.py +53 -10
  22. portacode/connection/handlers/session.py +705 -53
  23. portacode/connection/handlers/system_handlers.py +142 -8
  24. portacode/connection/handlers/tab_factory.py +389 -0
  25. portacode/connection/handlers/terminal_handlers.py +150 -11
  26. portacode/connection/handlers/update_handler.py +61 -0
  27. portacode/connection/multiplex.py +60 -2
  28. portacode/connection/terminal.py +695 -28
  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/service.py +6 -0
  53. portacode/static/js/test-ntp-clock.html +63 -0
  54. portacode/static/js/utils/ntp-clock.js +232 -0
  55. portacode/utils/NTP_ARCHITECTURE.md +136 -0
  56. portacode/utils/__init__.py +1 -0
  57. portacode/utils/diff_apply.py +456 -0
  58. portacode/utils/diff_renderer.py +371 -0
  59. portacode/utils/ntp_clock.py +65 -0
  60. portacode-1.4.11.dev0.dist-info/METADATA +298 -0
  61. portacode-1.4.11.dev0.dist-info/RECORD +97 -0
  62. {portacode-0.3.4.dev0.dist-info → portacode-1.4.11.dev0.dist-info}/WHEEL +1 -1
  63. portacode-1.4.11.dev0.dist-info/top_level.txt +3 -0
  64. test_modules/README.md +296 -0
  65. test_modules/__init__.py +1 -0
  66. test_modules/test_device_online.py +44 -0
  67. test_modules/test_file_operations.py +743 -0
  68. test_modules/test_git_status_ui.py +370 -0
  69. test_modules/test_login_flow.py +50 -0
  70. test_modules/test_navigate_testing_folder.py +361 -0
  71. test_modules/test_play_store_screenshots.py +294 -0
  72. test_modules/test_terminal_buffer_performance.py +261 -0
  73. test_modules/test_terminal_interaction.py +80 -0
  74. test_modules/test_terminal_loading_race_condition.py +95 -0
  75. test_modules/test_terminal_start.py +56 -0
  76. testing_framework/.env.example +21 -0
  77. testing_framework/README.md +334 -0
  78. testing_framework/__init__.py +17 -0
  79. testing_framework/cli.py +326 -0
  80. testing_framework/core/__init__.py +1 -0
  81. testing_framework/core/base_test.py +336 -0
  82. testing_framework/core/cli_manager.py +177 -0
  83. testing_framework/core/hierarchical_runner.py +577 -0
  84. testing_framework/core/playwright_manager.py +520 -0
  85. testing_framework/core/runner.py +447 -0
  86. testing_framework/core/shared_cli_manager.py +234 -0
  87. testing_framework/core/test_discovery.py +112 -0
  88. testing_framework/requirements.txt +12 -0
  89. portacode-0.3.4.dev0.dist-info/METADATA +0 -236
  90. portacode-0.3.4.dev0.dist-info/RECORD +0 -27
  91. portacode-0.3.4.dev0.dist-info/top_level.txt +0 -1
  92. {portacode-0.3.4.dev0.dist-info → portacode-1.4.11.dev0.dist-info}/entry_points.txt +0 -0
  93. {portacode-0.3.4.dev0.dist-info → portacode-1.4.11.dev0.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,236 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: portacode
3
- Version: 0.3.4.dev0
4
- Summary: Portacode CLI client and SDK
5
- Home-page: https://github.com/portacode/portacode
6
- Author: Meena Erian
7
- Classifier: Programming Language :: Python :: 3
8
- Classifier: License :: OSI Approved :: MIT License
9
- Classifier: Operating System :: OS Independent
10
- Requires-Python: >=3.8
11
- Description-Content-Type: text/markdown
12
- License-File: LICENSE
13
- Requires-Dist: click>=8.0
14
- Requires-Dist: platformdirs>=3.0
15
- Requires-Dist: cryptography>=41.0
16
- Requires-Dist: websockets>=12.0
17
- Requires-Dist: pyperclip>=1.8
18
- Requires-Dist: psutil>=5.9
19
- Requires-Dist: pyte>=0.8
20
- Requires-Dist: pywinpty>=2.0; platform_system == "Windows"
21
- Provides-Extra: dev
22
- Requires-Dist: black; extra == "dev"
23
- Requires-Dist: flake8; extra == "dev"
24
- Requires-Dist: pytest; extra == "dev"
25
-
26
- # Portacode
27
-
28
- **An AI-first, mobile-first IDE and admin tool, made with love and passion by software engineers, for software engineers.**
29
-
30
- 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.
31
-
32
- ## ✨ Why Portacode?
33
-
34
- - **🤖 AI-First**: Built from the ground up with AI integration in mind
35
- - **📱 Mobile-First**: Code and administrate from your phone or tablet
36
- - **🌍 Global Access**: Connect to your devices from anywhere with internet
37
- - **🔐 Secure**: HTTPS encrypted with RSA key authentication
38
- - **⚡ Fast Setup**: Get connected in under 60 seconds
39
- - **🔄 Always Connected**: Automatic reconnection and persistent service options
40
- - **🆓 Free Account**: Create your account and start connecting immediately
41
- - **🖥️ Cross-Platform**: Works on Windows, macOS, and Linux
42
-
43
- ## 🚀 Quick Start
44
-
45
- ### 1. Install Portacode
46
-
47
- ```bash
48
- pip install portacode
49
- ```
50
-
51
- ### 2. Connect Your Device
52
-
53
- ```bash
54
- portacode connect
55
- ```
56
-
57
- Follow the on-screen instructions to:
58
- - Visit [https://remote.portacode.com](https://remote.portacode.com)
59
- - Create your free account
60
- - Add your device using the generated key
61
- - Start coding and administrating!
62
-
63
- ### 3. Access Your Development Environment
64
-
65
- Once connected, you can:
66
- - Open terminal sessions from the web dashboard
67
- - Execute commands remotely
68
- - Monitor system status
69
- - Access your development environment from any device
70
-
71
- ## 💡 Use Cases
72
-
73
- ### Remote Development
74
- ```bash
75
- # Connect your development machine
76
- portacode connect
77
-
78
- # Now code, build, and debug from anywhere - even your phone
79
- ```
80
-
81
- ### Server Administration
82
- ```bash
83
- # For a persistent connection, install system-wide first
84
- sudo pip install portacode --system
85
-
86
- # Then install as a service
87
- sudo portacode service install
88
-
89
- # Your server is now accessible 24/7 from the web dashboard
90
- ```
91
-
92
- ### Mobile Development
93
- ```bash
94
- # Connect your desktop/laptop
95
- portacode connect
96
-
97
- # Code on-the-go from your mobile device with a full IDE experience
98
- ```
99
-
100
- ### Team Collaboration
101
- ```bash
102
- # Connect shared development environments
103
- portacode connect
104
-
105
- # Enable team members to access shared resources securely
106
- ```
107
-
108
- ## 🔧 Essential Commands
109
-
110
- ### Basic Usage
111
- ```bash
112
- # Start a connection (runs until closed)
113
- portacode connect
114
-
115
- # Run connection in background
116
- portacode connect --detach
117
-
118
- # Check version
119
- portacode --version
120
-
121
- # Get help
122
- portacode --help
123
- ```
124
-
125
- ### Service Management
126
- ```bash
127
- # For system services, install package system-wide first
128
- sudo pip install portacode --system
129
-
130
- # Install persistent service (auto-start on boot)
131
- sudo portacode service install
132
-
133
- # Check service status
134
- sudo portacode service status
135
-
136
- # Stop the service
137
- sudo portacode service stop
138
-
139
- # Remove the service
140
- sudo portacode service uninstall
141
- ```
142
-
143
- ## 🌐 Web Dashboard
144
-
145
- Access your connected devices at [https://remote.portacode.com](https://remote.portacode.com)
146
-
147
- **Current Features:**
148
- - Real-time terminal access
149
- - System monitoring
150
- - Device management
151
- - Multi-device switching
152
- - Secure authentication
153
-
154
- **Coming Soon:**
155
- - AI-powered code assistance
156
- - Mobile-optimized IDE interface
157
- - File management and editing
158
- - Collaborative development tools
159
-
160
- ## 🔐 Security
161
-
162
- - **RSA Key Authentication**: Each device gets a unique RSA key pair
163
- - **HTTPS Encrypted**: All communication is encrypted in transit
164
- - **No Passwords**: Key-based authentication eliminates password risks
165
- - **Revocable Access**: Remove devices instantly from the web dashboard
166
- - **Local Key Storage**: Private keys never leave your device
167
-
168
- ## 🆘 Troubleshooting
169
-
170
- ### Connection Issues
171
- ```bash
172
- # Check if another connection is running
173
- portacode connect
174
-
175
- # View service logs
176
- sudo portacode service status --verbose
177
- ```
178
-
179
- ### Service Installation Issues
180
- ```bash
181
- # If service commands fail, ensure system-wide installation
182
- sudo pip install portacode --system
183
-
184
- # Then try service installation again
185
- sudo portacode service install
186
- ```
187
-
188
- ### Clipboard Issues (Linux)
189
- ```bash
190
- # Install clipboard support
191
- sudo apt-get install xclip
192
- ```
193
-
194
- ### Key Management
195
- Key files are stored in:
196
- - **Linux**: `~/.local/share/portacode/keys/`
197
- - **macOS**: `~/Library/Application Support/portacode/keys/`
198
- - **Windows**: `%APPDATA%\portacode\keys\`
199
-
200
- ## 🌱 Early Stage Project
201
-
202
- **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:
203
-
204
- - **👥 Community Feedback**: Does this solve a real problem for you?
205
- - **🤝 Contributors**: Help us build the IDE of the future
206
- - **📢 Early Adopters**: Try it out and let us know what you think
207
- - **💡 Feature Ideas**: What would make your remote development workflow better?
208
-
209
- **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.
210
-
211
- ## 📞 Get In Touch
212
-
213
- - **Email**: hi@menas.pro
214
- - **Support**: support@portacode.com
215
- - **GitHub**: [https://github.com/portacode/portacode](https://github.com/portacode/portacode)
216
-
217
- ## 🤝 Contributing
218
-
219
- We welcome all forms of contribution:
220
- - 🐛 **Bug Reports**: Found something broken? Let us know!
221
- - ✨ **Feature Requests**: What would make Portacode better for you?
222
- - 📖 **Documentation**: Help others get started
223
- - 💻 **Code Contributions**: Help us build the future of remote development
224
- - 💬 **Feedback**: Tell us if you find this useful!
225
-
226
- Check out our [GitHub repository](https://github.com/portacode/portacode) to get started.
227
-
228
- ## 📄 License
229
-
230
- MIT License - see [LICENSE](LICENSE) file for details.
231
-
232
- ---
233
-
234
- **Get started today**: `pip install portacode && portacode connect`
235
-
236
- *Built with ❤️ and ☕ by passionate software engineers*
@@ -1,27 +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=Ns6kVynGC2eqrfabjdvEUAO4Je37Mu1MrcEpDoG1iAo,523
5
- portacode/cli.py,sha256=xEn3ACNKI_dU2PBdYkOACbG0uZZRYaXLsIAKDSr2614,14790
6
- portacode/data.py,sha256=5-s291bv8J354myaHm1Y7CQZTZyRzMU3TGe5U4hb-FA,1591
7
- portacode/keypair.py,sha256=PAcOYqlVLOoZTPYi6LvLjfsY6BkrWbLOhSZLb8r5sHs,3635
8
- portacode/service.py,sha256=kL4uP9SmSAsq2c_w27tiyghxShn4_jMy6-Q30tTYjmw,16251
9
- portacode/connection/README.md,sha256=f9rbuIEKa7cTm9C98rCiBbEtbiIXQU11esGSNhSMiJg,883
10
- portacode/connection/__init__.py,sha256=atqcVGkViIEd7pRa6cP2do07RJOM0UWpbnz5zXjGktU,250
11
- portacode/connection/client.py,sha256=2KTJtOGnyXlB2Kfq2LA9sRsPL2HNoNZbViD-qfM2wL0,7755
12
- portacode/connection/multiplex.py,sha256=P3jMo-Wm-RWpQ_aV1d73z8wWzjUvRfCZTmceWdkScYc,2087
13
- portacode/connection/terminal.py,sha256=Htk0_sOVNv5QY_qxXqYtgicWwdJL75xGfeJm8JGUqbU,8164
14
- portacode/connection/handlers/README.md,sha256=HsLZG1QK1JNm67HsgL6WoDg9nxzKXxwkc5fJPFJdX5g,12169
15
- portacode/connection/handlers/__init__.py,sha256=TcdXXNQY6wtE6VVZaBfIxGJJKHBqbueUDegSGGuzo2o,1081
16
- portacode/connection/handlers/base.py,sha256=4oi62s8RfKqNtx_6X6zRK__MF6w_WGqcnJOvgrGrUxU,3868
17
- portacode/connection/handlers/file_handlers.py,sha256=LQVavJTAFy9xaINRYUN5qSCiavfZf0sVhUz5ZHILju0,7095
18
- portacode/connection/handlers/registry.py,sha256=MkZkYa2nmUVHwd_z27Ba6bhytrKjkrg-kX-rEDi41oc,3864
19
- portacode/connection/handlers/session.py,sha256=RH7MFfrt9HHXV0AebgBFHQSksF0uO-YVFtZi8zRbvoY,12301
20
- portacode/connection/handlers/system_handlers.py,sha256=RkjDw-pnDr-QE61InCSXtJ2E5ozLnYRrAkketbbd2oo,5160
21
- portacode/connection/handlers/terminal_handlers.py,sha256=vA8OYwGvTp-qVeyK_EMTJrK7a1lPNvVaq5bxkFPV2mI,4343
22
- portacode-0.3.4.dev0.dist-info/LICENSE,sha256=2FGbCnUDgRYuQTkB1O1dUUpu5CVAjK1j4_p6ack9Z54,1066
23
- portacode-0.3.4.dev0.dist-info/METADATA,sha256=9D_QScVmKCNEG42Ga_ughA2j_Lz1geUL0QBJm2zZUSk,6771
24
- portacode-0.3.4.dev0.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
25
- portacode-0.3.4.dev0.dist-info/entry_points.txt,sha256=lLUUL-BM6_wwe44Xv0__5NQ1BnAz6jWjSMFvZdWW3zU,48
26
- portacode-0.3.4.dev0.dist-info/top_level.txt,sha256=U_n6hYjK7CBYFzYluuG-AP8UouIIQLCObIj6-WtG3Go,10
27
- portacode-0.3.4.dev0.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- portacode