vuer-cli 0.0.3__py3-none-any.whl → 0.0.5__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.
vuer_cli/upgrade.py CHANGED
@@ -1,159 +1,144 @@
1
1
  """Upgrade command - upgrade an environment in environment.json to latest version."""
2
2
 
3
- from dataclasses import dataclass
3
+ import json
4
4
  from pathlib import Path
5
- from typing import Optional
6
5
 
7
- import json
6
+ from params_proto import proto
8
7
 
9
8
  from .envs_publish import Hub
10
9
  from .sync import Sync, _extract_backend_error
11
10
  from .utils import is_dry_run, print_error
12
11
 
13
12
 
14
- @dataclass
13
+ @proto
15
14
  class Upgrade:
16
- """Upgrade a single environment in environment.json to the latest version.
17
-
18
- Usage:
19
- vuer upgrade some-environment-name
20
- """
21
-
22
- # Primary usage is positional: `vuer upgrade some-environment-name`.
23
- env: Optional[str] = None # Environment name to upgrade (no version part)
24
- # Kept for params-proto compatibility; not used in the new workflow.
25
- version: Optional[str] = None
26
-
27
- def __call__(self) -> int:
28
- """Execute upgrade command."""
29
- try:
30
- env_name = (self.env or "").strip()
31
- if not env_name:
32
- raise ValueError(
33
- "Missing environment name. Usage: vuer upgrade some-environment-name"
34
- )
35
-
36
- cwd = Path.cwd()
37
- env_json_path = cwd / "environment.json"
38
- if not env_json_path.exists():
39
- raise FileNotFoundError(
40
- "environment.json not found. Cannot upgrade environments."
41
- )
42
-
43
- try:
44
- with env_json_path.open("r", encoding="utf-8") as f:
45
- data = json.load(f)
46
- except json.JSONDecodeError as e:
47
- raise ValueError(f"Invalid environment.json: {e}") from e
48
-
49
- deps = data.get("dependencies") or {}
50
- if not isinstance(deps, dict):
51
- raise ValueError(
52
- "environment.json 'dependencies' field must be an object"
53
- )
54
-
55
- current_version = deps.get(env_name)
56
- if not isinstance(current_version, str) or not current_version:
57
- raise ValueError(
58
- f"Environment '{env_name}' not found in environment.json; nothing to upgrade."
59
- )
60
-
61
- dry_run = is_dry_run()
62
-
63
- if dry_run:
64
- print(
65
- f"[INFO] (dry-run) Would check latest version for '{env_name}', "
66
- f"current version is '{current_version}'."
67
- )
68
- print(
69
- "[INFO] (dry-run) Skipping upgrade and sync (no network calls).")
70
- return 0
71
-
72
- # Real upgrade: require hub configuration
73
- if not Hub.url:
74
- raise RuntimeError(
75
- "Missing VUER_HUB_URL. Please set the VUER_HUB_URL environment variable "
76
- "or pass --hub.url on the command line."
77
- )
78
- if not Hub.auth_token:
79
- raise RuntimeError(
80
- "Missing VUER_AUTH_TOKEN. Please set the VUER_AUTH_TOKEN environment "
81
- "variable or pass --hub.auth-token on the command line."
82
- )
83
-
84
- latest_version = _fetch_latest_version(env_name)
85
-
86
- if latest_version == current_version:
87
- print(
88
- f"[INFO] Environment '{env_name}' is already at latest version "
89
- f"({current_version})."
90
- )
91
- return 0
92
-
93
- # Update environment.json with the new version and run sync
94
- deps[env_name] = latest_version
95
- data["dependencies"] = deps
96
- with env_json_path.open("w", encoding="utf-8") as f:
97
- json.dump(data, f, indent=2, ensure_ascii=False)
98
- f.write("\n")
99
-
100
- print(
101
- f"[INFO] Upgraded {env_name} from {current_version} to {latest_version} "
102
- "in environment.json. Running sync..."
103
- )
104
- return Sync()()
105
-
106
- except (FileNotFoundError, ValueError, RuntimeError) as e:
107
- print_error(str(e))
108
- return 1
109
- except Exception as e:
110
- print_error(f"Unexpected error: {e}")
111
- return 1
112
-
15
+ """Upgrade a single environment in environment.json to the latest version.
113
16
 
114
- def _fetch_latest_version(env_name: str) -> str:
115
- """Call backend /environments/latest-by-name to get latest versionId for env_name."""
116
- import requests # Lazy import
17
+ Usage:
18
+ vuer upgrade some-environment-name
19
+ """
117
20
 
118
- params = {"name": env_name}
119
- url = f"{Hub.url.rstrip('/')}/environments/latest-by-name"
120
- headers = {
121
- "Authorization": f"Bearer {Hub.auth_token}"
122
- } if Hub.auth_token else {}
21
+ # Required positional arg: environment name to upgrade (no version part)
22
+ env: str
123
23
 
24
+ def __call__(self) -> int:
25
+ """Execute upgrade command."""
124
26
  try:
125
- response = requests.get(url, params=params, headers=headers,
126
- timeout=300)
127
- response.raise_for_status()
128
- except requests.exceptions.HTTPError as e:
129
- resp = getattr(e, "response", None)
130
- status = resp.status_code if resp is not None else "unknown"
131
- detail = _extract_backend_error(resp)
132
- raise RuntimeError(
133
- f"Failed to fetch latest version for '{env_name}' ({status}): {detail}"
134
- ) from e
135
- except requests.exceptions.RequestException as e:
136
- raise RuntimeError(
137
- f"Failed to fetch latest version for '{env_name}': {e}"
138
- ) from e
27
+ env_name = self.env.strip()
28
+
29
+ cwd = Path.cwd()
30
+ env_json_path = cwd / "environment.json"
31
+ if not env_json_path.exists():
32
+ raise FileNotFoundError(
33
+ "environment.json not found. Cannot upgrade environments."
34
+ )
35
+
36
+ try:
37
+ with env_json_path.open("r", encoding="utf-8") as f:
38
+ data = json.load(f)
39
+ except json.JSONDecodeError as e:
40
+ raise ValueError(f"Invalid environment.json: {e}") from e
41
+
42
+ deps = data.get("dependencies") or {}
43
+ if not isinstance(deps, dict):
44
+ raise ValueError("environment.json 'dependencies' field must be an object")
45
+
46
+ current_version = deps.get(env_name)
47
+ if not isinstance(current_version, str) or not current_version:
48
+ raise ValueError(
49
+ f"Environment '{env_name}' not found in environment.json; nothing to upgrade."
50
+ )
51
+
52
+ dry_run = is_dry_run()
139
53
 
140
- data = response.json()
54
+ if dry_run:
55
+ print(
56
+ f"[INFO] (dry-run) Would check latest version for '{env_name}', "
57
+ f"current version is '{current_version}'."
58
+ )
59
+ print("[INFO] (dry-run) Skipping upgrade and sync (no network calls).")
60
+ return 0
141
61
 
142
- # Error response format: {"error": "name is required"}
143
- if "error" in data:
62
+ # Real upgrade: require hub configuration
63
+ if not Hub.url:
144
64
  raise RuntimeError(
145
- f"Failed to fetch latest version for '{env_name}': {data['error']}"
65
+ "Missing VUER_HUB_URL. Please set the VUER_HUB_URL environment variable "
66
+ "or pass --hub.url on the command line."
67
+ )
68
+ # Try to get token from credentials file if not in environment
69
+ auth_token = Hub.get_auth_token()
70
+ if not auth_token:
71
+ raise RuntimeError(
72
+ "Missing VUER_AUTH_TOKEN. Please run 'vuer login' to authenticate, "
73
+ "or set the VUER_AUTH_TOKEN environment variable."
146
74
  )
147
75
 
148
- payload = data.get("data")
149
- if not isinstance(payload, dict):
150
- raise ValueError(
151
- "Invalid response format: 'data' field must be an object")
76
+ latest_version = _fetch_latest_version(env_name)
152
77
 
153
- version_id = payload.get("versionId")
154
- if not version_id:
155
- raise ValueError(
156
- "Invalid response format: 'data.versionId' field is required"
78
+ if latest_version == current_version:
79
+ print(
80
+ f"[INFO] Environment '{env_name}' is already at latest version "
81
+ f"({current_version})."
157
82
  )
83
+ return 0
84
+
85
+ # Update environment.json with the new version and run sync
86
+ deps[env_name] = latest_version
87
+ data["dependencies"] = deps
88
+ with env_json_path.open("w", encoding="utf-8") as f:
89
+ json.dump(data, f, indent=2, ensure_ascii=False)
90
+ f.write("\n")
91
+
92
+ print(
93
+ f"[INFO] Upgraded {env_name} from {current_version} to {latest_version} "
94
+ "in environment.json. Running sync..."
95
+ )
96
+ return Sync().run()
158
97
 
159
- return str(version_id)
98
+ except (FileNotFoundError, ValueError, RuntimeError) as e:
99
+ print_error(str(e))
100
+ return 1
101
+ except Exception as e:
102
+ print_error(f"Unexpected error: {e}")
103
+ return 1
104
+
105
+
106
+ def _fetch_latest_version(env_name: str) -> str:
107
+ """Call backend /environments/latest-by-name to get latest versionId for env_name."""
108
+ import requests # Lazy import
109
+
110
+ params = {"name": env_name}
111
+ url = f"{Hub.url.rstrip('/')}/environments/latest-by-name"
112
+ auth_token = Hub.get_auth_token()
113
+ headers = {"Authorization": f"Bearer {auth_token}"} if auth_token else {}
114
+
115
+ try:
116
+ response = requests.get(url, params=params, headers=headers, timeout=300)
117
+ response.raise_for_status()
118
+ except requests.exceptions.HTTPError as e:
119
+ resp = getattr(e, "response", None)
120
+ status = resp.status_code if resp is not None else "unknown"
121
+ detail = _extract_backend_error(resp)
122
+ raise RuntimeError(
123
+ f"Failed to fetch latest version for '{env_name}' ({status}): {detail}"
124
+ ) from e
125
+ except requests.exceptions.RequestException as e:
126
+ raise RuntimeError(f"Failed to fetch latest version for '{env_name}': {e}") from e
127
+
128
+ data = response.json()
129
+
130
+ # Error response format: {"error": "name is required"}
131
+ if "error" in data:
132
+ raise RuntimeError(
133
+ f"Failed to fetch latest version for '{env_name}': {data['error']}"
134
+ )
135
+
136
+ payload = data.get("data")
137
+ if not isinstance(payload, dict):
138
+ raise ValueError("Invalid response format: 'data' field must be an object")
139
+
140
+ version_id = payload.get("versionId")
141
+ if not version_id:
142
+ raise ValueError("Invalid response format: 'data.versionId' field is required")
143
+
144
+ return str(version_id)
vuer_cli/utils.py CHANGED
@@ -1,51 +1,24 @@
1
1
  """Shared utilities for Vuer CLI."""
2
2
 
3
3
  import itertools
4
+ import os
4
5
  import threading
5
6
  import time
6
7
 
7
- from params_proto import EnvVar, proto
8
-
9
-
10
- @proto.prefix
11
- class Config:
12
- """CLI configuration settings."""
13
-
14
- def _get_dry_run(self) -> bool:
15
- """Whether to run in dry-run mode (no real network calls).
16
-
17
- Controlled by VUER_CLI_DRY_RUN environment variable:
18
- - unset -> False (real API calls, default)
19
- - "0" -> False (real API calls)
20
- - "false"/"False" -> False
21
- - anything else -> True (dry-run)
22
- """
23
- # Use EnvVar with default=None to detect if it's actually set
24
- dry_run_env = EnvVar("VUER_CLI_DRY_RUN", default=None)
25
- value = dry_run_env.get()
26
- if value is not None:
27
- # Environment variable is set, check its value
28
- return value not in ("0", "false", "False")
29
-
30
- # Default to real execution when nothing is set
31
- return False
32
-
33
- # Use a property to compute dry_run dynamically
34
- @property
35
- def dry_run(self) -> bool:
36
- return self._get_dry_run()
37
-
38
-
39
- # Create singleton instance
40
- _config = Config()
41
-
42
8
 
43
9
  def is_dry_run() -> bool:
44
10
  """Whether to run in dry-run mode (no real network calls).
45
-
46
- This is a convenience function that uses the Config singleton.
11
+
12
+ Controlled by VUER_CLI_DRY_RUN environment variable:
13
+ - unset -> False (real API calls, default)
14
+ - "0" -> False (real API calls)
15
+ - "false"/"False" -> False
16
+ - anything else -> True (dry-run)
47
17
  """
48
- return _config.dry_run
18
+ value = os.environ.get("VUER_CLI_DRY_RUN")
19
+ if value is not None:
20
+ return value not in ("0", "false", "False")
21
+ return False
49
22
 
50
23
 
51
24
  def print_error(message: str) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vuer-cli
3
- Version: 0.0.3
3
+ Version: 0.0.5
4
4
  Summary: A Python CLI for Vuer, a real-time 3D visualization library
5
5
  Project-URL: Homepage, https://github.com/vuer-ai/vuer-cli
6
6
  Project-URL: Repository, https://github.com/vuer-ai/vuer-cli
@@ -18,10 +18,16 @@ Classifier: Programming Language :: Python :: 3.10
18
18
  Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
20
  Requires-Python: >=3.8
21
- Requires-Dist: params-proto>=3.0.0rc9
21
+ Requires-Dist: params-proto>=3.2.3
22
22
  Requires-Dist: requests>=2.31.0
23
23
  Requires-Dist: tqdm>=4.66.0
24
24
  Provides-Extra: all
25
+ Requires-Dist: mcap-ros2-support>=0.5.0; extra == 'all'
26
+ Requires-Dist: mcap>=1.1.0; extra == 'all'
27
+ Requires-Dist: numpy>=1.24.0; extra == 'all'
28
+ Requires-Dist: opencv-python>=4.8.0; extra == 'all'
29
+ Requires-Dist: pandas>=2.0.0; extra == 'all'
30
+ Requires-Dist: vuer>=0.0.81; extra == 'all'
25
31
  Provides-Extra: docs
26
32
  Requires-Dist: furo; extra == 'docs'
27
33
  Requires-Dist: myst-parser; extra == 'docs'
@@ -30,6 +36,17 @@ Requires-Dist: sphinx-copybutton; extra == 'docs'
30
36
  Requires-Dist: sphinx>=4.0; extra == 'docs'
31
37
  Requires-Dist: tomli>=1.1.0; (python_version < '3.11') and extra == 'docs'
32
38
  Provides-Extra: example
39
+ Provides-Extra: mcap
40
+ Requires-Dist: mcap-ros2-support>=0.5.0; extra == 'mcap'
41
+ Requires-Dist: mcap>=1.1.0; extra == 'mcap'
42
+ Requires-Dist: numpy>=1.24.0; extra == 'mcap'
43
+ Requires-Dist: opencv-python>=4.8.0; extra == 'mcap'
44
+ Requires-Dist: pandas>=2.0.0; extra == 'mcap'
45
+ Provides-Extra: viz
46
+ Requires-Dist: numpy>=1.24.0; extra == 'viz'
47
+ Requires-Dist: opencv-python>=4.8.0; extra == 'viz'
48
+ Requires-Dist: pandas>=2.0.0; extra == 'viz'
49
+ Requires-Dist: vuer>=0.0.81; extra == 'viz'
33
50
  Description-Content-Type: text/markdown
34
51
 
35
52
  # Vuer Hub Environment Manager
@@ -41,7 +58,13 @@ software packages.
41
58
  ## Installation
42
59
 
43
60
  ```bash
44
- pip install vuer-cli
61
+ pip install vuer-cli==0.0.4
62
+ ```
63
+
64
+ or with uv:
65
+
66
+ ```bash
67
+ uv add vuer-cli==0.0.4
45
68
  ```
46
69
 
47
70
  ## Environment Variables
@@ -57,6 +80,7 @@ pip install vuer-cli
57
80
  |----------------|-----------------------------------------------------------------------|
58
81
  | `vuer` | Show top-level help and list available commands |
59
82
  | `vuer --help` | Show detailed CLI help |
83
+ | `login` | Authenticate with Vuer Hub using OAuth Device Flow |
60
84
  | `sync` | Sync all environments from environment.json dependencies (like npm install) |
61
85
  | `add` | Add an environment dependency to environment.json |
62
86
  | `remove` | Remove an environment dependency from environment.json |
@@ -66,18 +90,47 @@ pip install vuer-cli
66
90
 
67
91
  ## Usage
68
92
 
69
- Quick start — configure environment variables
93
+ ### Authentication
70
94
 
71
- `VUER_HUB_URL` is required and has no default. Set it to the base URL of your Vuer Hub API.
95
+ The easiest way to authenticate is using the `login` command:
96
+
97
+ ```bash
98
+ # Set the Hub URL first
99
+ export VUER_HUB_URL="https://hub.vuer.ai/api"
100
+
101
+ # Login with dev environment (default)
102
+ vuer login
103
+
104
+ # Or login with production environment
105
+ vuer login --env production
106
+ ```
107
+
108
+ **After successful authentication:**
109
+ - ✅ Credentials are automatically saved and configured
110
+ - ✅ **Vuer CLI will automatically use the saved credentials** - no manual setup needed!
111
+ - ✅ Works immediately in the current terminal
112
+ - ✅ Works in all new terminals (auto-configured)
113
+ - ✅ Cross-platform support (Windows, macOS, Linux)
114
+
115
+ **How it works:**
116
+ 1. Saves credentials to `~/.vuer/credentials` (used automatically by CLI)
117
+ 2. Creates shell script at `~/.vuer/env.sh` (for manual use if needed)
118
+ 3. **Windows**: Sets user environment variables via `setx`
119
+ 4. **macOS/Linux**: Automatically adds to your shell config (~/.zshrc or ~/.bashrc)
120
+
121
+ **Manual setup (optional):**
122
+
123
+ If you prefer to set environment variables manually:
72
124
 
73
125
  ```bash
74
126
  export VUER_HUB_URL="https://hub.vuer.ai/api"
75
- # Optional: token for private hubs or authenticated operations
76
127
  export VUER_AUTH_TOKEN="eyJhbGci..."
77
128
  # Optional: enable dry-run mode to simulate operations (no network changes)
78
129
  export VUER_CLI_DRY_RUN="1"
79
130
  ```
80
131
 
132
+ ### Basic Commands
133
+
81
134
  ```bash
82
135
  # Sync all environments from environment.json dependencies
83
136
  # Reads environment.json in current directory, validates dependencies,
@@ -0,0 +1,22 @@
1
+ vuer_cli/__init__.py,sha256=IyB44__IHu_PHuviTe8EULikOAJ45k-52kWbNpF8Lo0,387
2
+ vuer_cli/add.py,sha256=yEjyRhZOgDCndiNEw7qo-rvfshnQNckY1dQbs1MMbkk,2298
3
+ vuer_cli/envs_publish.py,sha256=XyI8nz6xZcadMjggz8BpLky8d9K_2v0ZafDPPIMq0w8,12159
4
+ vuer_cli/envs_pull.py,sha256=9DHxMcqUc88SD6SSAZL_LMAeACmaGmpQNkgw2furSnw,6700
5
+ vuer_cli/login.py,sha256=TrcBoI2kMMNDJnH8bkWMJBExtzW9n4-6JqZ2mePUsyg,15230
6
+ vuer_cli/main.py,sha256=wdaa_VVtlPNdLSC-Rge5QYqzdWhUBgoEB1p5-T_uKUQ,2559
7
+ vuer_cli/mcap_extractor.py,sha256=zQEaiWhmfEDSf0Tej7J0arkAxTHjCDaW73fb_OjHwNA,35529
8
+ vuer_cli/remove.py,sha256=GmvX9pxNCY8fj3jRxWzACF1jWDhxs4Ec7Pf75P7Y3M0,3310
9
+ vuer_cli/sync.py,sha256=d9x8E9woORHL94Qm3CGzFyxZT_XEugpwIj_YHHuUvqo,12776
10
+ vuer_cli/upgrade.py,sha256=eDV3V-Z6M4HBJCy-ppSN2r41AIHJv1fjtEAur9whVBM,4685
11
+ vuer_cli/utils.py,sha256=L7r1Lm-j6n7NqVjUJm5n8id7ZKuPrkOH3x-tP6BNx74,2670
12
+ vuer_cli/scripts/demcap.py,sha256=eLRWXg7lRRLKfYEdg3LtoDyROq0IbQP46bljcZmvQJQ,5415
13
+ vuer_cli/scripts/mcap_playback.py,sha256=7xv8NZcGP3XHwBzcy8AzAKk74kZCN4CztqmKvlmez0o,22329
14
+ vuer_cli/scripts/minimap.py,sha256=51xur7LsWx39ar0VseiqpxuChk8KybcGmI8LWf35xTI,11100
15
+ vuer_cli/scripts/ptc_utils.py,sha256=T55BY3plXwxtZTvbpesThYvE6vZB6aBT_iklwWjXg2Y,15018
16
+ vuer_cli/scripts/viz_ptc_cams.py,sha256=H0QdYuW-sHT9qj06pdpum_jTdHJmajUw0ZDCjUjmNjo,21062
17
+ vuer_cli/scripts/viz_ptc_proxie.py,sha256=inp-o6U2LkgwKa35OCaEz7LpLWMTw0qgzftKnb19oIE,14405
18
+ vuer_cli-0.0.5.dist-info/METADATA,sha256=3V9ocrPDLPyX7qDGPZXO8pkc8Pk7YEPBt_2OvQ2Ok9g,10501
19
+ vuer_cli-0.0.5.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
20
+ vuer_cli-0.0.5.dist-info/entry_points.txt,sha256=pH846erbxBfJpIj151Ps_UzgWIYPeIjl5gxZyTZn_7E,45
21
+ vuer_cli-0.0.5.dist-info/licenses/LICENSE,sha256=MGF-inVBUaGe2mEjqT0g6XsHIXwoNXgNHqD7Z1MzR0k,1063
22
+ vuer_cli-0.0.5.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- vuer_cli/__init__.py,sha256=IyB44__IHu_PHuviTe8EULikOAJ45k-52kWbNpF8Lo0,387
2
- vuer_cli/add.py,sha256=b6v1z8xHlphg-nY-KQ-Oly8MdRWs7qBh4Cn1TKqlmOM,3348
3
- vuer_cli/envs_publish.py,sha256=6RSPaWQ7_VxwD9UcQDBdoz9HGreyqKJWVGAbtJOW7Uw,12798
4
- vuer_cli/envs_pull.py,sha256=IfxcKjft8VA2OtE-6wRYBBD4RNKyZBfINnYf5tBq1Lk,7214
5
- vuer_cli/main.py,sha256=dOOqfGCR-Ls9dxqgZr6df_n2cp29Uu24rL4eiUuVQoI,3549
6
- vuer_cli/remove.py,sha256=HJQ98evnSF-5Fe1HVH_nAJWMbTZm5iQaZL_L4ViPD5Q,4125
7
- vuer_cli/sync.py,sha256=AKe5xupfGzHJfsJKriVcIOh2iakMhegfrncDZP-kkk4,13976
8
- vuer_cli/upgrade.py,sha256=lM5sxHwvo25Ojr8FpyXz4paVPnmHXFLWQZjV1ebxsFs,5677
9
- vuer_cli/utils.py,sha256=zdt_3daFLVzp_9Rsrv5xm-a2YpLecyYyHiHqrbzxnrg,3433
10
- vuer_cli-0.0.3.dist-info/METADATA,sha256=Xg4CjuY13258vnUvONZsK5JOwQyBkGJlaeLSCsDA020,8771
11
- vuer_cli-0.0.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
12
- vuer_cli-0.0.3.dist-info/entry_points.txt,sha256=pH846erbxBfJpIj151Ps_UzgWIYPeIjl5gxZyTZn_7E,45
13
- vuer_cli-0.0.3.dist-info/licenses/LICENSE,sha256=MGF-inVBUaGe2mEjqT0g6XsHIXwoNXgNHqD7Z1MzR0k,1063
14
- vuer_cli-0.0.3.dist-info/RECORD,,