cloudscope 0.2.0__tar.gz → 0.3.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.
Files changed (57) hide show
  1. cloudscope-0.3.0/PKG-INFO +241 -0
  2. {cloudscope-0.2.0 → cloudscope-0.3.0}/pyproject.toml +2 -1
  3. cloudscope-0.2.0/PKG-INFO +0 -22
  4. {cloudscope-0.2.0 → cloudscope-0.3.0}/.github/workflows/python-publish.yml +0 -0
  5. {cloudscope-0.2.0 → cloudscope-0.3.0}/.gitignore +0 -0
  6. {cloudscope-0.2.0 → cloudscope-0.3.0}/README.md +0 -0
  7. {cloudscope-0.2.0 → cloudscope-0.3.0}/package-lock.json +0 -0
  8. {cloudscope-0.2.0 → cloudscope-0.3.0}/package.json +0 -0
  9. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/__init__.py +0 -0
  10. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/__main__.py +0 -0
  11. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/app.py +0 -0
  12. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/auth/__init__.py +0 -0
  13. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/auth/aws.py +0 -0
  14. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/auth/drive_oauth.py +0 -0
  15. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/auth/gcp.py +0 -0
  16. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/backends/__init__.py +0 -0
  17. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/backends/base.py +0 -0
  18. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/backends/drive.py +0 -0
  19. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/backends/gcs.py +0 -0
  20. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/backends/registry.py +0 -0
  21. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/backends/s3.py +0 -0
  22. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/config.py +0 -0
  23. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/models/__init__.py +0 -0
  24. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/models/cloud_file.py +0 -0
  25. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/models/sync_state.py +0 -0
  26. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/models/transfer.py +0 -0
  27. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/sync/__init__.py +0 -0
  28. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/sync/differ.py +0 -0
  29. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/sync/engine.py +0 -0
  30. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/sync/plan.py +0 -0
  31. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/sync/resolver.py +0 -0
  32. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/sync/state.py +0 -0
  33. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/transfer/__init__.py +0 -0
  34. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/transfer/manager.py +0 -0
  35. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/transfer/progress.py +0 -0
  36. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/__init__.py +0 -0
  37. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/commands.py +0 -0
  38. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/modals/__init__.py +0 -0
  39. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/modals/confirm_dialog.py +0 -0
  40. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/modals/download_dialog.py +0 -0
  41. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/modals/new_folder.py +0 -0
  42. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/modals/sync_dialog.py +0 -0
  43. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/modals/upload_dialog.py +0 -0
  44. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/screens/__init__.py +0 -0
  45. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/screens/auth_setup.py +0 -0
  46. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/screens/browse.py +0 -0
  47. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/screens/settings.py +0 -0
  48. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/screens/sync_config.py +0 -0
  49. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/styles/cloudscope.tcss +0 -0
  50. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/widgets/__init__.py +0 -0
  51. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/widgets/app_footer.py +0 -0
  52. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/widgets/breadcrumb.py +0 -0
  53. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/widgets/cloud_tree.py +0 -0
  54. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/widgets/file_table.py +0 -0
  55. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/widgets/preview_panel.py +0 -0
  56. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/widgets/status_bar.py +0 -0
  57. {cloudscope-0.2.0 → cloudscope-0.3.0}/src/cloudscope/tui/widgets/transfer_panel.py +0 -0
@@ -0,0 +1,241 @@
1
+ Metadata-Version: 2.4
2
+ Name: cloudscope
3
+ Version: 0.3.0
4
+ Summary: TUI for browsing and syncing files across S3, GCS, and Google Drive
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: aiofiles>=23.0.0
7
+ Requires-Dist: boto3>=1.28.0
8
+ Requires-Dist: google-api-python-client>=2.90.0
9
+ Requires-Dist: google-auth-httplib2>=0.1.0
10
+ Requires-Dist: google-auth-oauthlib>=1.0.0
11
+ Requires-Dist: google-cloud-storage>=2.10.0
12
+ Requires-Dist: humanize>=4.0.0
13
+ Requires-Dist: platformdirs>=3.0.0
14
+ Requires-Dist: textual>=1.0.0
15
+ Provides-Extra: dev
16
+ Requires-Dist: moto>=4.0; extra == 'dev'
17
+ Requires-Dist: mypy>=1.5; extra == 'dev'
18
+ Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
19
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
20
+ Requires-Dist: pytest>=7.0; extra == 'dev'
21
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
22
+ Requires-Dist: textual-dev>=1.0.0; extra == 'dev'
23
+ Description-Content-Type: text/markdown
24
+
25
+ # CloudScope
26
+
27
+ A terminal UI for browsing, downloading, uploading, and bi-directionally syncing files across **AWS S3**, **Google Cloud Storage**, and **Google Drive**.
28
+
29
+ Built with [Textual](https://textual.textualize.io/) for a keyboard-driven, Linear.app-inspired dark interface.
30
+
31
+ ## Features
32
+
33
+ - **Multi-backend browsing** — Switch between S3, GCS, and Google Drive with a single keypress (`1`, `2`, `3`)
34
+ - **Lazy-loading tree sidebar** — Expand buckets/drives on demand without loading everything upfront
35
+ - **Sortable file table** — Click column headers to sort by name, size, modified date, or type
36
+ - **File preview** — Metadata panel appears when a file is highlighted (size, modified date, ETag, content type)
37
+ - **Downloads and uploads** — File picker dialogs for selecting local paths
38
+ - **Folder creation** — Create new folders/prefixes directly from the TUI
39
+ - **Bi-directional sync** — Three-way diff engine with conflict resolution (newer wins, local wins, remote wins, keep both, or ask)
40
+ - **Command palette** — Press `Ctrl+K` to search and run any command
41
+ - **Settings screen** — Configure default backend, AWS profile/region, GCP project, Drive OAuth credentials
42
+ - **Auth setup** — Guided authentication testing for each backend
43
+
44
+ ## Requirements
45
+
46
+ - Python 3.11+
47
+ - AWS credentials (for S3) — environment variables, `~/.aws/credentials`, or IAM role
48
+ - GCP credentials (for GCS) — Application Default Credentials (`gcloud auth application-default login`)
49
+ - OAuth2 client secrets (for Google Drive) — `client_secrets.json` placed in config directory
50
+
51
+ ## Installation
52
+
53
+ ### From source
54
+
55
+ ```bash
56
+ git clone https://github.com/your-username/cloudscope.git
57
+ cd cloudscope
58
+ pip install -e .
59
+ ```
60
+
61
+ ### With dev dependencies
62
+
63
+ ```bash
64
+ pip install -e ".[dev]"
65
+ ```
66
+
67
+ ### Run
68
+
69
+ ```bash
70
+ cloudscope
71
+ ```
72
+
73
+ Or via module:
74
+
75
+ ```bash
76
+ python -m cloudscope
77
+ ```
78
+
79
+ ## Authentication Setup
80
+
81
+ ### AWS S3
82
+
83
+ CloudScope uses standard boto3 credential resolution. Any of the following will work:
84
+
85
+ - Environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`)
86
+ - Shared credentials file (`~/.aws/credentials`)
87
+ - AWS config file (`~/.aws/config`) with named profiles
88
+ - IAM instance role (on EC2)
89
+
90
+ Configure a specific profile in Settings (`,`) or pass it through the config file at `~/.config/cloudscope/config.toml`.
91
+
92
+ ### Google Cloud Storage
93
+
94
+ Uses [Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials):
95
+
96
+ ```bash
97
+ gcloud auth application-default login
98
+ ```
99
+
100
+ Or point to a service account key in Settings.
101
+
102
+ ### Google Drive
103
+
104
+ Requires OAuth2 consent flow:
105
+
106
+ 1. Create OAuth credentials in the [Google Cloud Console](https://console.cloud.google.com/apis/credentials)
107
+ 2. Download the client secrets JSON
108
+ 3. Place it at `~/.config/cloudscope/drive_client_secrets.json` (or configure the path in Settings)
109
+ 4. Press `a` in CloudScope to run the auth flow — a browser window will open for consent
110
+
111
+ The token is persisted at `~/.config/cloudscope/drive_token.json` and refreshed automatically.
112
+
113
+ ## Keyboard Shortcuts
114
+
115
+ ### Browsing
116
+
117
+ | Key | Action |
118
+ |---|---|
119
+ | `1` | Switch to S3 |
120
+ | `2` | Switch to GCS |
121
+ | `3` | Switch to Google Drive |
122
+ | `d` | Download selected file |
123
+ | `u` | Upload a file |
124
+ | `n` | Create new folder |
125
+ | `Delete` | Delete selected file |
126
+ | `r` | Refresh current view |
127
+ | `Tab` | Focus next panel |
128
+ | `Shift+Tab` | Focus previous panel |
129
+ | `Ctrl+K` | Open command palette |
130
+ | `s` | Open sync configuration |
131
+ | `,` | Open settings |
132
+ | `a` | Open auth setup |
133
+ | `?` | Show help |
134
+ | `q` | Quit |
135
+
136
+ ### In file table
137
+
138
+ | Key | Action |
139
+ |---|---|
140
+ | `Up`/`Down` | Navigate files |
141
+ | `Enter` | Open folder or select file |
142
+ | Click column header | Sort by that column |
143
+
144
+ ## Configuration
145
+
146
+ Settings are stored at `~/.config/cloudscope/config.toml`:
147
+
148
+ ```toml
149
+ default_backend = "s3"
150
+ max_concurrent_transfers = 3
151
+
152
+ [backends.s3]
153
+ profile = "default"
154
+ region = "us-east-1"
155
+
156
+ [backends.gcs]
157
+ project = "my-project-id"
158
+
159
+ [backends.drive]
160
+ client_secrets_path = "/path/to/client_secrets.json"
161
+ ```
162
+
163
+ All settings can also be edited from the TUI via the Settings screen (`,`).
164
+
165
+ ## Project Structure
166
+
167
+ ```
168
+ src/cloudscope/
169
+ ├── app.py # Main Textual application
170
+ ├── config.py # TOML config management
171
+ ├── __main__.py # CLI entry point
172
+ ├── auth/
173
+ │ ├── aws.py # AWS profile listing and client creation
174
+ │ ├── gcp.py # GCS client creation (ADC or service account)
175
+ │ └── drive_oauth.py # Google Drive OAuth2 flow
176
+ ├── backends/
177
+ │ ├── base.py # CloudBackend Protocol and error hierarchy
178
+ │ ├── registry.py # Backend factory (register/get/list)
179
+ │ ├── s3.py # AWS S3 backend (boto3)
180
+ │ ├── gcs.py # Google Cloud Storage backend
181
+ │ └── drive.py # Google Drive backend (path-to-ID cache, export)
182
+ ├── models/
183
+ │ ├── cloud_file.py # CloudFile, CloudFileType, CloudLocation
184
+ │ ├── transfer.py # TransferJob, TransferDirection, TransferStatus
185
+ │ └── sync_state.py # SyncRecord, SyncConflict, SyncPlan, etc.
186
+ ├── sync/
187
+ │ ├── state.py # SQLite-backed sync state persistence
188
+ │ ├── differ.py # Three-way diff algorithm
189
+ │ ├── resolver.py # Conflict resolution strategies
190
+ │ ├── plan.py # Converts SyncDiff to executable SyncPlan
191
+ │ └── engine.py # Sync orchestrator (diff → plan → execute)
192
+ ├── transfer/
193
+ │ ├── manager.py # Concurrent transfer queue (asyncio.Semaphore)
194
+ │ └── progress.py # Progress adapter for SDK callbacks
195
+ └── tui/
196
+ ├── commands.py # Command palette provider (Ctrl+K)
197
+ ├── screens/
198
+ │ ├── browse.py # Main browsing screen
199
+ │ ├── settings.py # Settings form
200
+ │ ├── sync_config.py # Sync configuration and execution
201
+ │ └── auth_setup.py # Guided auth testing
202
+ ├── modals/
203
+ │ ├── confirm_dialog.py
204
+ │ ├── download_dialog.py
205
+ │ ├── upload_dialog.py
206
+ │ ├── new_folder.py
207
+ │ └── sync_dialog.py # Sync conflict resolution
208
+ ├── widgets/
209
+ │ ├── status_bar.py # AppHeader (slim 1-line header)
210
+ │ ├── app_footer.py # Context-sensitive keybind hints
211
+ │ ├── cloud_tree.py # Lazy-loading tree sidebar
212
+ │ ├── file_table.py # Sortable file listing (DataTable)
213
+ │ ├── breadcrumb.py # Path breadcrumb with › separators
214
+ │ ├── preview_panel.py # File metadata display
215
+ │ └── transfer_panel.py# Transfer progress bar
216
+ └── styles/
217
+ └── cloudscope.tcss # Linear-inspired dark theme
218
+ ```
219
+
220
+ ## Development
221
+
222
+ ```bash
223
+ # Install with dev dependencies
224
+ pip install -e ".[dev]"
225
+
226
+ # Lint
227
+ ruff check src/
228
+
229
+ # Type check
230
+ mypy src/cloudscope/
231
+
232
+ # Test
233
+ pytest
234
+
235
+ # Run with Textual dev tools (live CSS reloading, etc.)
236
+ textual run --dev cloudscope.app:CloudScopeApp
237
+ ```
238
+
239
+ ## License
240
+
241
+ MIT
@@ -4,8 +4,9 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "cloudscope"
7
- version = "0.2.0"
7
+ version = "0.3.0"
8
8
  description = "TUI for browsing and syncing files across S3, GCS, and Google Drive"
9
+ readme = "README.md"
9
10
  requires-python = ">=3.11"
10
11
  dependencies = [
11
12
  "textual>=1.0.0",
cloudscope-0.2.0/PKG-INFO DELETED
@@ -1,22 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: cloudscope
3
- Version: 0.2.0
4
- Summary: TUI for browsing and syncing files across S3, GCS, and Google Drive
5
- Requires-Python: >=3.11
6
- Requires-Dist: aiofiles>=23.0.0
7
- Requires-Dist: boto3>=1.28.0
8
- Requires-Dist: google-api-python-client>=2.90.0
9
- Requires-Dist: google-auth-httplib2>=0.1.0
10
- Requires-Dist: google-auth-oauthlib>=1.0.0
11
- Requires-Dist: google-cloud-storage>=2.10.0
12
- Requires-Dist: humanize>=4.0.0
13
- Requires-Dist: platformdirs>=3.0.0
14
- Requires-Dist: textual>=1.0.0
15
- Provides-Extra: dev
16
- Requires-Dist: moto>=4.0; extra == 'dev'
17
- Requires-Dist: mypy>=1.5; extra == 'dev'
18
- Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
19
- Requires-Dist: pytest-cov>=4.0; extra == 'dev'
20
- Requires-Dist: pytest>=7.0; extra == 'dev'
21
- Requires-Dist: ruff>=0.1.0; extra == 'dev'
22
- Requires-Dist: textual-dev>=1.0.0; extra == 'dev'
File without changes
File without changes
File without changes
File without changes