plotly-cloud 0.1.0__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.
@@ -0,0 +1,198 @@
1
+ """Custom exceptions for Plotly Cloud CLI."""
2
+
3
+ from typing import Optional
4
+
5
+
6
+ class PlotlyCloudError(Exception):
7
+ """Base exception for all Plotly Cloud CLI errors."""
8
+
9
+ def __init__(self, message: str, details: Optional[str] = None):
10
+ """Initialize exception with message and optional details."""
11
+ super().__init__(message)
12
+ self.message = message
13
+ self.details = details
14
+
15
+ def __str__(self) -> str:
16
+ """Return formatted error message."""
17
+ if self.details:
18
+ return f"{self.message}: {self.details}"
19
+ return self.message
20
+
21
+
22
+ class AuthenticationError(PlotlyCloudError):
23
+ """Raised when authentication fails."""
24
+
25
+ pass
26
+
27
+
28
+ class ConfigurationError(PlotlyCloudError):
29
+ """Raised when configuration is invalid or missing."""
30
+
31
+ pass
32
+
33
+
34
+ class DeploymentError(PlotlyCloudError):
35
+ """Raised when deployment operations fail."""
36
+
37
+ pass
38
+
39
+
40
+ class ApplicationError(PlotlyCloudError):
41
+ """Raised when application operations fail."""
42
+
43
+ pass
44
+
45
+
46
+ # Authentication-specific exceptions
47
+ class OAuthClientError(AuthenticationError):
48
+ """Raised when OAuth client operations fail."""
49
+
50
+ pass
51
+
52
+
53
+ class TokenError(AuthenticationError):
54
+ """Raised when token operations fail."""
55
+
56
+ pass
57
+
58
+
59
+ class CredentialError(AuthenticationError):
60
+ """Raised when credential operations fail."""
61
+
62
+ pass
63
+
64
+
65
+ class ForbiddenError(AuthenticationError):
66
+ """Raised when access is forbidden (HTTP 403)."""
67
+
68
+ pass
69
+
70
+
71
+ # Configuration-specific exceptions
72
+ class CloudConfigError(ConfigurationError):
73
+ """Raised when cloud configuration operations fail."""
74
+
75
+ pass
76
+
77
+
78
+ class EnvironmentError(ConfigurationError):
79
+ """Raised when environment configuration is invalid."""
80
+
81
+ pass
82
+
83
+
84
+ # Deployment-specific exceptions
85
+ class DependencyValidationError(DeploymentError):
86
+ """Raised when dependency validation fails."""
87
+
88
+ pass
89
+
90
+
91
+ class PackagingError(DeploymentError):
92
+ """Raised when packaging operations fail."""
93
+
94
+ pass
95
+
96
+
97
+ class UploadError(DeploymentError):
98
+ """Raised when upload operations fail."""
99
+
100
+ pass
101
+
102
+
103
+ class AppCreationError(DeploymentError):
104
+ """Raised when app creation fails."""
105
+
106
+ pass
107
+
108
+
109
+ class AppPublishError(DeploymentError):
110
+ """Raised when app publishing fails."""
111
+
112
+ pass
113
+
114
+
115
+ class DeploymentClientError(DeploymentError):
116
+ """Raised when deployment client operations fail."""
117
+
118
+ pass
119
+
120
+
121
+ # Application-specific exceptions
122
+ class ModuleImportError(ApplicationError):
123
+ """Raised when module import fails."""
124
+
125
+ pass
126
+
127
+
128
+ class DashAppError(ApplicationError):
129
+ """Raised when Dash app operations fail."""
130
+
131
+ pass
132
+
133
+
134
+ class ServerError(ApplicationError):
135
+ """Raised when server operations fail."""
136
+
137
+ pass
138
+
139
+
140
+ # Network-specific exceptions
141
+ class APIError(PlotlyCloudError):
142
+ """Raised when API operations fail."""
143
+
144
+ def __init__(
145
+ self,
146
+ message: str,
147
+ status_code: Optional[int] = None,
148
+ details: Optional[str] = None,
149
+ ):
150
+ """Initialize API error with optional status code."""
151
+ super().__init__(message, details)
152
+ self.status_code = status_code
153
+
154
+ def __str__(self) -> str:
155
+ """Return formatted error message with status code."""
156
+ msg = self.message
157
+ if self.status_code:
158
+ msg = f"{msg} (HTTP {self.status_code})"
159
+ if self.details:
160
+ msg = f"{msg}: {self.details}"
161
+ return msg
162
+
163
+
164
+ class NetworkError(PlotlyCloudError):
165
+ """Raised when network operations fail."""
166
+
167
+ pass
168
+
169
+
170
+ class TimeoutError(PlotlyCloudError):
171
+ """Raised when operations timeout."""
172
+
173
+ pass
174
+
175
+
176
+ # File system exceptions
177
+ class FileSystemError(PlotlyCloudError):
178
+ """Raised when file system operations fail."""
179
+
180
+ pass
181
+
182
+
183
+ class FileNotFoundError(FileSystemError):
184
+ """Raised when required files are not found."""
185
+
186
+ pass
187
+
188
+
189
+ class FilePermissionError(FileSystemError):
190
+ """Raised when file permission operations fail."""
191
+
192
+ pass
193
+
194
+
195
+ class FileSizeError(FileSystemError):
196
+ """Raised when file size limits are exceeded."""
197
+
198
+ pass
@@ -0,0 +1,294 @@
1
+ Metadata-Version: 2.4
2
+ Name: plotly-cloud
3
+ Version: 0.1.0
4
+ Summary: CLI for interacting with Plotly Cloud to deploy Dash apps
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.9
7
+ Requires-Dist: dash>=2.0.0
8
+ Requires-Dist: httpx<1.0.0,>=0.24.0
9
+ Requires-Dist: nest-asyncio>=1.6.0
10
+ Requires-Dist: rich>=10.0.0
11
+ Requires-Dist: tomli-w>=1.2.0
12
+ Requires-Dist: tomli>=2.2.1
13
+ Description-Content-Type: text/markdown
14
+
15
+ # Plotly Cloud CLI
16
+
17
+ A command-line interface for interacting with Plotly Cloud to publish and manage Dash applications.
18
+
19
+ ## Features
20
+
21
+ - 🔐 **Authentication**: Login/logout with Plotly Cloud using OAuth
22
+ - 🚀 **Local Development**: Run Dash applications locally with comprehensive dev tools
23
+ - 📦 **Publish**: Publish Dash applications to Plotly Cloud with metadata management
24
+ - ⚙️ **Environment Configuration**: Centralized cloud configuration with staging/production support
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ pip install plotly-cloud
30
+ ```
31
+
32
+ ## Quick Start
33
+
34
+ ### 1. Login to Plotly Cloud
35
+
36
+ ```bash
37
+ plotly login
38
+ ```
39
+
40
+ This will open your browser for OAuth authentication.
41
+
42
+ ### 2. Run a Dash Application
43
+
44
+ ```bash
45
+ plotly run app:app
46
+ ```
47
+
48
+ This runs your Dash app from the `app` module, using the `app` variable.
49
+
50
+ ### 3. Publish to Plotly Cloud
51
+
52
+ ```bash
53
+ # For new applications (first publish)
54
+ plotly publish --name "My App" --description "My application description"
55
+
56
+ # For existing applications (with default polling)
57
+ plotly publish
58
+
59
+ # Publish without polling status
60
+ plotly publish --poll-status=false
61
+ ```
62
+
63
+ ### 4. Logout
64
+
65
+ ```bash
66
+ plotly logout
67
+ ```
68
+
69
+ ## Environment Configuration
70
+
71
+ The CLI uses a `cloud-env.toml` file for environment-specific configuration (OAuth client IDs, API URLs). This file is gitignored and should be created during development or at packaging time.
72
+
73
+ ## Usage
74
+
75
+ ### Authentication Commands
76
+
77
+ #### Login
78
+ ```bash
79
+ plotly login [--browser | --no-browser]
80
+ ```
81
+
82
+ Options:
83
+ - `--browser`: Open browser for authentication (default)
84
+ - `--no-browser`: Don't open browser automatically
85
+
86
+ #### Logout
87
+ ```bash
88
+ plotly logout
89
+ ```
90
+
91
+ #### Check Current User
92
+ ```bash
93
+ plotly whoami
94
+ ```
95
+
96
+ Show current user information if logged in with a valid token. If the token is invalid, it will automatically clear the credentials.
97
+
98
+ ### Running Applications
99
+
100
+ #### Basic Usage
101
+ ```bash
102
+ plotly run <module:variable>
103
+ ```
104
+
105
+ Examples:
106
+ ```bash
107
+ plotly run app:app # Run app from app.py
108
+ plotly run myapp:dashboard # Run dashboard from myapp.py
109
+ plotly run main # Run from main.py (looks for first Dash app)
110
+ ```
111
+
112
+ #### Advanced Options
113
+
114
+ ```bash
115
+ plotly run app:app --host 0.0.0.0 --port 8080 --debug
116
+ ```
117
+
118
+ **Server Options:**
119
+ - `--host`: Host IP address (default: 127.0.0.1)
120
+ - `--port, -p`: Port number (default: 8050)
121
+ - `--proxy`: Proxy configuration
122
+ - `--debug, -d`: Enable debug mode
123
+
124
+ **Development Tools:**
125
+ - `--dev-tools-ui`: Enable dev tools UI
126
+ - `--dev-tools-props-check`: Enable component prop validation
127
+ - `--dev-tools-serve-dev-bundles`: Enable serving dev bundles
128
+ - `--dev-tools-hot-reload`: Enable hot reloading
129
+ - `--dev-tools-hot-reload-interval`: Hot reload polling interval (default: 3.0s)
130
+ - `--dev-tools-hot-reload-watch-interval`: File watch interval (default: 0.5s)
131
+ - `--dev-tools-hot-reload-max-retry`: Max failed reload attempts (default: 8)
132
+ - `--dev-tools-silence-routes-logging`: Silence Werkzeug route logging
133
+ - `--dev-tools-disable-version-check`: Disable Dash version upgrade check
134
+ - `--dev-tools-prune-errors`: Prune tracebacks to user code only
135
+
136
+ ### Publishing Commands
137
+
138
+ #### Publish Application
139
+ ```bash
140
+ plotly publish [OPTIONS]
141
+ ```
142
+
143
+ Publish your Dash application to Plotly Cloud with automatic status polling.
144
+
145
+ **Options:**
146
+ - `--project-path`: Path to project directory (default: current directory)
147
+ - `--config`: Path to configuration file (default: plotly-cloud.toml)
148
+ - `--name`: Application name (required for first publish)
149
+ - `--description`: Application description (optional)
150
+ - `--output`: Output path for publish zip file (default: temporary file)
151
+ - `--keep-zip`: Keep the publish zip file after upload
152
+ - `--poll-status`: Poll publish status until completion (default: true)
153
+ - `--poll-interval`: Polling interval in seconds (default: 1.0)
154
+ - `--poll-timeout`: Polling timeout in seconds (default: 180 = 3 minutes)
155
+
156
+ **Examples:**
157
+ ```bash
158
+ # Publish with default settings (includes status polling)
159
+ plotly publish
160
+
161
+ # Publish new app with custom name and description
162
+ plotly publish --name "My Dashboard" --description "Sales analytics dashboard"
163
+
164
+ # Publish without status polling
165
+ plotly publish --poll-status=false
166
+
167
+ # Publish with custom polling settings
168
+ plotly publish --poll-interval=2.0 --poll-timeout=300
169
+
170
+ # Publish and keep the zip file
171
+ plotly publish --output=my-app.zip --keep-zip
172
+ ```
173
+
174
+ #### Check Application Status
175
+ ```bash
176
+ plotly status [OPTIONS]
177
+ ```
178
+
179
+ Get current status and details of your published application.
180
+
181
+ **Options:**
182
+ - `--project-path`: Path to project directory (default: current directory)
183
+ - `--config`: Path to configuration file (default: plotly-cloud.toml)
184
+
185
+ **Example:**
186
+ ```bash
187
+ plotly status
188
+ ```
189
+
190
+ ## Requirements
191
+
192
+ - Python 3.9+
193
+
194
+ ### Python Dependencies
195
+
196
+ - `httpx>=0.24.0` - HTTP client for API requests
197
+ - `dash>=2.0.0` - Dash framework
198
+ - `rich>=10.0.0` - Rich terminal formatting
199
+
200
+ ### Development Dependencies
201
+
202
+ - `pytest>=6.0` - Testing framework
203
+ - `ruff>=0.1.0` - Code linting and formatting
204
+ - `pyright>=1.1.0` - Type checking
205
+
206
+ ## Development
207
+
208
+ ### Setup
209
+
210
+ We use [`uv`](https://docs.astral.sh/uv/) to manage dependencies and [Just](https://github.com/casey/just) is used for task automation. Install them and use our Justfile for common development tasks:
211
+
212
+ 1. Clone the repository
213
+ 2. Install uv: `curl -LsSf https://astral.sh/uv/install.sh | sh` or on windows: `powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"`
214
+ 3. Install Just: `cargo install just` or see [installation docs](https://github.com/casey/just#installation)
215
+ 4. Setup the development environment:
216
+ ```bash
217
+ # Install dependencies
218
+ just install
219
+
220
+ # Setup cloud environment configuration
221
+ just setup-cloud-env "your-staging-client-id" "your-production-client-id"
222
+
223
+ # Install CLI in development mode
224
+ just install-cli
225
+ ```
226
+
227
+ ### Development Commands
228
+
229
+ Run `just` or `just --list` to see all available commands:
230
+
231
+ ```bash
232
+ # Testing
233
+ just test # Run all tests
234
+ just test-cov # Run tests with coverage
235
+ just test-file tests/test_commands.py # Run specific test file
236
+
237
+ # Code Quality
238
+ just lint # Run linting
239
+ just lint-fix # Run linting with auto-fix
240
+ just format # Format code
241
+ just quality # Run all quality checks (lint + typecheck + test)
242
+
243
+ # Cloud Configuration
244
+ just setup-cloud-env <staging_id> [production_id] # Setup cloud config
245
+ just show-cloud-config # Display current configuration
246
+
247
+ # Publishing
248
+ just publish [path] # Publish to cloud (default: current directory)
249
+
250
+ # Development
251
+ just install-cli # Install CLI in development mode
252
+ just test-cli # Test CLI after installation
253
+ just run-example app:app # Run example Dash app
254
+
255
+ # Maintenance
256
+ just clean # Clean build artifacts
257
+ just build # Build package
258
+ ```
259
+
260
+ ### Alternative Setup (without Just)
261
+
262
+ If you prefer not to use Just:
263
+
264
+ 1. Create a virtual environment:
265
+ ```bash
266
+ python -m venv .venv
267
+ source .venv/bin/activate # On Windows: .venv\Scripts\activate
268
+ ```
269
+ 2. Install in development mode:
270
+ ```bash
271
+ pip install -e ".[dev]"
272
+ ```
273
+
274
+ ### Project Structure
275
+
276
+ ```
277
+ plotly-cloud-cli/
278
+ ├── plotly_cloud/
279
+ │ ├── __init__.py # Package initialization
280
+ │ ├── cli.py # Main CLI entry point
281
+ │ └── _commands.py # Command implementations
282
+ ├── pyproject.toml # Project configuration
283
+ ├── uv.lock # Dependency lock file
284
+ ├── .gitignore # Git ignore rules
285
+ └── README.md # This file
286
+ ```
287
+
288
+ ## License
289
+
290
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
291
+
292
+ ## Support
293
+
294
+ For issues and questions, please open an issue on the GitHub repository.
@@ -0,0 +1,21 @@
1
+ plotly_cloud/__init__.py,sha256=wpj79Ze3y-ZOaVREZBKU1wGt87HKfGyXM6-iHipgc7c,55
2
+ plotly_cloud/_api_types.py,sha256=_sKJb6Bk7e-2ucLRGmdr8Nq9-8G-BLU2EtVLA25HkKM,1103
3
+ plotly_cloud/_changes.py,sha256=YQJGChUzSGCgQOVnsA98vqWLARaY893UqVePYsCAhh8,2084
4
+ plotly_cloud/_cloud_env.py,sha256=8hlYB2x6V7KsNmy80MKRNDmxuQiPna71_nhK7haF23E,2941
5
+ plotly_cloud/_commands.py,sha256=FbJGOBs1VJ171eTqoOgfBIAlq_x1VoaMhf0HBElLKkM,35015
6
+ plotly_cloud/_definitions.py,sha256=UmzzhV6evNNWYW_eAvnbdplaoSKWuTQtWuJ1AkjFgis,2388
7
+ plotly_cloud/_deploy.py,sha256=Fpsu7L9mTyh3wEODfMMlAWmFBzfsoYgjg_IK6xG97RE,16198
8
+ plotly_cloud/_devtool_hooks.py,sha256=j16E5x5UiWwkgTjSBEFtQ71NOTaAYkofM9CIAfNMnbE,1504
9
+ plotly_cloud/_devtool_publish_rpc.py,sha256=-cCUB0KIiM2n5pb2_K5o4H6W9YaRSh4KAJEpYcpzIdk,10641
10
+ plotly_cloud/_oauth.py,sha256=yCi6tn17bLmhZiajUcliWjxZ9mEt0iMXIS9dGojPsH0,12377
11
+ plotly_cloud/_parser.py,sha256=EoyehZZRy_A8PHO2yTMUkJcXTgztgh-7gAQF2uaP640,5795
12
+ plotly_cloud/cli.py,sha256=keez1KpXxZEDLWYo58VnvzPBG6mctMf1aNqDWGqfvq4,10474
13
+ plotly_cloud/cloud-env.toml,sha256=Em7c0Q3vaCqXmWdEH-Re32eo4Na_HVQ7mJyMFY80KZ8,248
14
+ plotly_cloud/cloud_devtools.css,sha256=3y2Q9NzM1arrkniLGZHfkiqtttuD5X7LkmCuxrkMRtI,3730
15
+ plotly_cloud/cloud_devtools.js,sha256=BQWc-dzs1EFmruXJJvZMphtj7JvR5RMKLjz0KTsvxJk,41840
16
+ plotly_cloud/exceptions.py,sha256=k5uvHh41oKWsRiVBSVFCMbtHygbkgTkq_uJJ1Q3wlG4,4033
17
+ plotly_cloud-0.1.0.dist-info/METADATA,sha256=wHowUtRnJchfzwTu8ZqRKWGzRGA-JWG2_4xMqZ2srYg,8173
18
+ plotly_cloud-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
19
+ plotly_cloud-0.1.0.dist-info/entry_points.txt,sha256=iZVffCSWjpG8Ht2HZAJDwZBmG-kVlIbH_V6SF8cwLNY,115
20
+ plotly_cloud-0.1.0.dist-info/licenses/LICENSE,sha256=ElWBU-rl1xjn3Pvcguv5MNomrIMao1mPtuT_j8Q6WaI,1068
21
+ plotly_cloud-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,5 @@
1
+ [console_scripts]
2
+ plotly = plotly_cloud.cli:main
3
+
4
+ [dash_hooks]
5
+ plotly_cloud_devtools = plotly_cloud._devtool_hooks
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Plotly, Inc.
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.