lr-gladiator 0.7.0__tar.gz → 0.8.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.
Potentially problematic release.
This version of lr-gladiator might be problematic. Click here for more details.
- lr_gladiator-0.8.0/PKG-INFO +181 -0
- lr_gladiator-0.8.0/README.md +158 -0
- {lr_gladiator-0.7.0 → lr_gladiator-0.8.0}/pyproject.toml +1 -1
- {lr_gladiator-0.7.0 → lr_gladiator-0.8.0}/src/gladiator/cli.py +82 -45
- lr_gladiator-0.8.0/src/lr_gladiator.egg-info/PKG-INFO +181 -0
- lr_gladiator-0.7.0/PKG-INFO +0 -90
- lr_gladiator-0.7.0/README.md +0 -67
- lr_gladiator-0.7.0/src/lr_gladiator.egg-info/PKG-INFO +0 -90
- {lr_gladiator-0.7.0 → lr_gladiator-0.8.0}/LICENSE +0 -0
- {lr_gladiator-0.7.0 → lr_gladiator-0.8.0}/setup.cfg +0 -0
- {lr_gladiator-0.7.0 → lr_gladiator-0.8.0}/src/gladiator/__init__.py +0 -0
- {lr_gladiator-0.7.0 → lr_gladiator-0.8.0}/src/gladiator/arena.py +0 -0
- {lr_gladiator-0.7.0 → lr_gladiator-0.8.0}/src/gladiator/config.py +0 -0
- {lr_gladiator-0.7.0 → lr_gladiator-0.8.0}/src/lr_gladiator.egg-info/SOURCES.txt +0 -0
- {lr_gladiator-0.7.0 → lr_gladiator-0.8.0}/src/lr_gladiator.egg-info/dependency_links.txt +0 -0
- {lr_gladiator-0.7.0 → lr_gladiator-0.8.0}/src/lr_gladiator.egg-info/entry_points.txt +0 -0
- {lr_gladiator-0.7.0 → lr_gladiator-0.8.0}/src/lr_gladiator.egg-info/requires.txt +0 -0
- {lr_gladiator-0.7.0 → lr_gladiator-0.8.0}/src/lr_gladiator.egg-info/top_level.txt +0 -0
- {lr_gladiator-0.7.0 → lr_gladiator-0.8.0}/tests/test_smoke.py +0 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lr-gladiator
|
|
3
|
+
Version: 0.8.0
|
|
4
|
+
Summary: CLI and Python client for Arena PLM (app.bom.com): login, get revisions, list/download attachments, and upload to working revisions.
|
|
5
|
+
Author-email: Jonas Estberger <jonas.estberger@lumenradio.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: Arena,PLM,BOM,attachments,CLI
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: requests>=2.32
|
|
15
|
+
Requires-Dist: typer>=0.12
|
|
16
|
+
Requires-Dist: rich>=13.7
|
|
17
|
+
Requires-Dist: pydantic>=2.8
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: build>=1.2.1; extra == "dev"
|
|
20
|
+
Requires-Dist: twine>=5.1.1; extra == "dev"
|
|
21
|
+
Requires-Dist: wheel; extra == "dev"
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# gladiator-arena
|
|
25
|
+
|
|
26
|
+
CLI + Python client for interacting with the Arena PLM.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install lr-gladiator
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick start
|
|
35
|
+
|
|
36
|
+
### 1) Create `login.json`
|
|
37
|
+
|
|
38
|
+
Interactive login (prompts for username/password):
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
gladiator login
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Non-interactive (for CI/CD):
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
gladiator login --username "$ARENA_USERNAME" --password "$ARENA_PASSWORD" --ci
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
By default, this stores session details at:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
~/.config/gladiator/login.json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 2) Common commands
|
|
57
|
+
|
|
58
|
+
Get the latest approved revision for an item:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
gladiator latest-approved 890-1001
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
List all files on an item (defaults to the latest approved revision):
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
gladiator list-files 890-1001
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Output JSON instead of a table:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
gladiator list-files 890-1001 --format json
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
List the Bill of Materials (BOM) for an item:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
gladiator bom 890-1001
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Recursively expand subassemblies up to two levels deep:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
gladiator bom 890-1001 --recursive --max-depth 2
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Download attached files to a directory named after the article:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
gladiator get-files 890-1001
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Specify a different output directory:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
gladiator get-files 890-1001 --out downloads/
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Recursively download all files in the full BOM tree:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
gladiator get-files 890-1001 --recursive
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Upload or update a file on the working revision:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
gladiator upload-file 890-1001 ./datasheet.pdf --category "CAD Data" --title "Datasheet"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 3) Output control
|
|
113
|
+
|
|
114
|
+
Most commands support a JSON output mode.
|
|
115
|
+
Example:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
gladiator bom 890-1001 --output json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Example sessions
|
|
122
|
+
|
|
123
|
+
#### Human-readable
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
$ gladiator list-files 101-1031
|
|
127
|
+
Files for 101-1031 rev (latest approved)
|
|
128
|
+
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
|
|
129
|
+
┃ Name ┃ Size ┃ Checksum ┃
|
|
130
|
+
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
|
|
131
|
+
│ Drawing.pdf │ 12345 │ d41d8cd98f00b204e… │
|
|
132
|
+
└──────────────────────────────────────┴───────┴─────────────────────┘
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### JSON output
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
$ gladiator list-files 101-1031 --format json
|
|
139
|
+
{
|
|
140
|
+
"article": "101-1031",
|
|
141
|
+
"revision": "EFFECTIVE",
|
|
142
|
+
"files": [
|
|
143
|
+
{
|
|
144
|
+
"filename": "Drawing.pdf",
|
|
145
|
+
"size": 12345,
|
|
146
|
+
"checksum": "d41d8cd98f00b204e9800998ecf8427e"
|
|
147
|
+
}
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Programmatic use
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from gladiator import ArenaClient, load_config
|
|
156
|
+
|
|
157
|
+
client = ArenaClient(load_config())
|
|
158
|
+
rev = client.get_latest_approved_revision("890-1001")
|
|
159
|
+
files = client.list_files("890-1001", rev)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Development
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
python -m pip install -e .[dev]
|
|
166
|
+
python -m build
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## FAQ
|
|
170
|
+
|
|
171
|
+
- **Where is the config kept?**
|
|
172
|
+
`~/.config/gladiator/login.json` (override with `GLADIATOR_CONFIG`)
|
|
173
|
+
|
|
174
|
+
- **How do I run non-interactively?**
|
|
175
|
+
Pass `--ci` together with `--username` and `--password` (or use environment variables).
|
|
176
|
+
|
|
177
|
+
- **What does `--recursive` do?**
|
|
178
|
+
Expands subassemblies and downloads or lists all contained items up to the given `--max-depth`.
|
|
179
|
+
|
|
180
|
+
- **How does Gladiator handle authentication?**
|
|
181
|
+
It performs a `/login` call and stores the resulting `arenaSessionId` for reuse. If it expires, re-run `gladiator login`.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# gladiator-arena
|
|
2
|
+
|
|
3
|
+
CLI + Python client for interacting with the Arena PLM.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install lr-gladiator
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
### 1) Create `login.json`
|
|
14
|
+
|
|
15
|
+
Interactive login (prompts for username/password):
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
gladiator login
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Non-interactive (for CI/CD):
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
gladiator login --username "$ARENA_USERNAME" --password "$ARENA_PASSWORD" --ci
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
By default, this stores session details at:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
~/.config/gladiator/login.json
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2) Common commands
|
|
34
|
+
|
|
35
|
+
Get the latest approved revision for an item:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
gladiator latest-approved 890-1001
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
List all files on an item (defaults to the latest approved revision):
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
gladiator list-files 890-1001
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Output JSON instead of a table:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
gladiator list-files 890-1001 --format json
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
List the Bill of Materials (BOM) for an item:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
gladiator bom 890-1001
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Recursively expand subassemblies up to two levels deep:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
gladiator bom 890-1001 --recursive --max-depth 2
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Download attached files to a directory named after the article:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
gladiator get-files 890-1001
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Specify a different output directory:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
gladiator get-files 890-1001 --out downloads/
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Recursively download all files in the full BOM tree:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
gladiator get-files 890-1001 --recursive
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Upload or update a file on the working revision:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
gladiator upload-file 890-1001 ./datasheet.pdf --category "CAD Data" --title "Datasheet"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 3) Output control
|
|
90
|
+
|
|
91
|
+
Most commands support a JSON output mode.
|
|
92
|
+
Example:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
gladiator bom 890-1001 --output json
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Example sessions
|
|
99
|
+
|
|
100
|
+
#### Human-readable
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
$ gladiator list-files 101-1031
|
|
104
|
+
Files for 101-1031 rev (latest approved)
|
|
105
|
+
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
|
|
106
|
+
┃ Name ┃ Size ┃ Checksum ┃
|
|
107
|
+
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
|
|
108
|
+
│ Drawing.pdf │ 12345 │ d41d8cd98f00b204e… │
|
|
109
|
+
└──────────────────────────────────────┴───────┴─────────────────────┘
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
#### JSON output
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
$ gladiator list-files 101-1031 --format json
|
|
116
|
+
{
|
|
117
|
+
"article": "101-1031",
|
|
118
|
+
"revision": "EFFECTIVE",
|
|
119
|
+
"files": [
|
|
120
|
+
{
|
|
121
|
+
"filename": "Drawing.pdf",
|
|
122
|
+
"size": 12345,
|
|
123
|
+
"checksum": "d41d8cd98f00b204e9800998ecf8427e"
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Programmatic use
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from gladiator import ArenaClient, load_config
|
|
133
|
+
|
|
134
|
+
client = ArenaClient(load_config())
|
|
135
|
+
rev = client.get_latest_approved_revision("890-1001")
|
|
136
|
+
files = client.list_files("890-1001", rev)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Development
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
python -m pip install -e .[dev]
|
|
143
|
+
python -m build
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## FAQ
|
|
147
|
+
|
|
148
|
+
- **Where is the config kept?**
|
|
149
|
+
`~/.config/gladiator/login.json` (override with `GLADIATOR_CONFIG`)
|
|
150
|
+
|
|
151
|
+
- **How do I run non-interactively?**
|
|
152
|
+
Pass `--ci` together with `--username` and `--password` (or use environment variables).
|
|
153
|
+
|
|
154
|
+
- **What does `--recursive` do?**
|
|
155
|
+
Expands subassemblies and downloads or lists all contained items up to the given `--max-depth`.
|
|
156
|
+
|
|
157
|
+
- **How does Gladiator handle authentication?**
|
|
158
|
+
It performs a `/login` call and stores the resulting `arenaSessionId` for reuse. If it expires, re-run `gladiator login`.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "lr-gladiator"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.8.0"
|
|
8
8
|
description = "CLI and Python client for Arena PLM (app.bom.com): login, get revisions, list/download attachments, and upload to working revisions."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -8,13 +8,33 @@ from typing import Optional
|
|
|
8
8
|
import typer
|
|
9
9
|
from rich import print
|
|
10
10
|
from rich.table import Table
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
from rich.status import Status
|
|
11
13
|
from getpass import getpass
|
|
12
14
|
import requests
|
|
13
15
|
import sys
|
|
16
|
+
import os
|
|
14
17
|
from .config import LoginConfig, save_config, load_config, save_config_raw, CONFIG_PATH
|
|
15
18
|
from .arena import ArenaClient, ArenaError
|
|
16
19
|
|
|
17
20
|
app = typer.Typer(add_completion=False, help="Arena PLM command-line utility")
|
|
21
|
+
console = Console()
|
|
22
|
+
|
|
23
|
+
# --- tiny helper to show a spinner when appropriate ---
|
|
24
|
+
from contextlib import contextmanager
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@contextmanager
|
|
28
|
+
def spinner(message: str, enabled: bool = True):
|
|
29
|
+
"""
|
|
30
|
+
Show a Rich spinner while the body executes.
|
|
31
|
+
Auto-disables if stdout is not a TTY (e.g., CI) or enabled=False.
|
|
32
|
+
"""
|
|
33
|
+
if enabled and sys.stdout.isatty():
|
|
34
|
+
with console.status(message, spinner="dots"):
|
|
35
|
+
yield
|
|
36
|
+
else:
|
|
37
|
+
yield
|
|
18
38
|
|
|
19
39
|
|
|
20
40
|
@app.command()
|
|
@@ -36,10 +56,7 @@ def login(
|
|
|
36
56
|
"CI/CD integration", help="Arena-Usage-Reason header"
|
|
37
57
|
),
|
|
38
58
|
):
|
|
39
|
-
"""Create or update ~/.config/gladiator/login.json for subsequent commands.
|
|
40
|
-
|
|
41
|
-
This performs a `/login` call against Arena and stores the JSON (including arenaSessionId) in login.json.
|
|
42
|
-
"""
|
|
59
|
+
"""Create or update ~/.config/gladiator/login.json for subsequent commands."""
|
|
43
60
|
if not username and not non_interactive:
|
|
44
61
|
username = typer.prompt("Email/username")
|
|
45
62
|
if not password and not non_interactive:
|
|
@@ -59,27 +76,22 @@ def login(
|
|
|
59
76
|
"User-Agent": "gladiator-arena/0.1",
|
|
60
77
|
}
|
|
61
78
|
url = f"{(base_url or '').rstrip('/')}/login"
|
|
62
|
-
resp = sess.post(
|
|
63
|
-
url, headers=headers, json={"email": username, "password": password}
|
|
64
|
-
)
|
|
65
79
|
try:
|
|
66
|
-
|
|
80
|
+
with spinner("Logging in…", enabled=sys.stdout.isatty()):
|
|
81
|
+
resp = sess.post(
|
|
82
|
+
url, headers=headers, json={"email": username, "password": password}
|
|
83
|
+
)
|
|
84
|
+
resp.raise_for_status()
|
|
67
85
|
except Exception as e:
|
|
68
86
|
typer.secho(
|
|
69
|
-
f"Login failed: {e} Body: {resp
|
|
87
|
+
f"Login failed: {e} Body: {getattr(resp, 'text', '')[:400]}",
|
|
88
|
+
fg=typer.colors.RED,
|
|
89
|
+
err=True,
|
|
70
90
|
)
|
|
71
91
|
raise typer.Exit(2)
|
|
72
92
|
|
|
73
93
|
data = resp.json()
|
|
74
|
-
|
|
75
|
-
# Merge our client settings alongside the session info into the same file (compatible with your bash scripts)
|
|
76
|
-
data.update(
|
|
77
|
-
{
|
|
78
|
-
"base_url": base_url,
|
|
79
|
-
"verify_tls": verify_tls,
|
|
80
|
-
"reason": reason,
|
|
81
|
-
}
|
|
82
|
-
)
|
|
94
|
+
data.update({"base_url": base_url, "verify_tls": verify_tls, "reason": reason})
|
|
83
95
|
save_config_raw(data)
|
|
84
96
|
print(f"[green]Saved session to {CONFIG_PATH}[/green]")
|
|
85
97
|
|
|
@@ -97,9 +109,13 @@ def latest_approved(
|
|
|
97
109
|
),
|
|
98
110
|
):
|
|
99
111
|
"""Print latest approved revision for the given item number."""
|
|
112
|
+
json_mode = (format or "").lower() == "json"
|
|
100
113
|
try:
|
|
101
|
-
|
|
102
|
-
|
|
114
|
+
with spinner(
|
|
115
|
+
f"Resolving latest approved revision for {item}…", enabled=not json_mode
|
|
116
|
+
):
|
|
117
|
+
rev = _client().get_latest_approved_revision(item)
|
|
118
|
+
if json_mode:
|
|
103
119
|
json.dump({"article": item, "revision": rev}, sys.stdout, indent=2)
|
|
104
120
|
sys.stdout.write("\n")
|
|
105
121
|
else:
|
|
@@ -124,9 +140,15 @@ def list_files(
|
|
|
124
140
|
None, "--format", "-f", help="Output format: human (default) or json"
|
|
125
141
|
),
|
|
126
142
|
):
|
|
143
|
+
json_mode = (format or "").lower() == "json"
|
|
127
144
|
try:
|
|
128
|
-
|
|
129
|
-
|
|
145
|
+
with spinner(
|
|
146
|
+
f"Listing files for {item} ({revision or 'EFFECTIVE'})…",
|
|
147
|
+
enabled=not json_mode,
|
|
148
|
+
):
|
|
149
|
+
files = _client().list_files(item, revision)
|
|
150
|
+
|
|
151
|
+
if json_mode:
|
|
130
152
|
json.dump(
|
|
131
153
|
{"article": item, "revision": revision, "files": files},
|
|
132
154
|
sys.stdout,
|
|
@@ -174,12 +196,19 @@ def bom(
|
|
|
174
196
|
),
|
|
175
197
|
):
|
|
176
198
|
"""List the BOM lines for an item revision."""
|
|
199
|
+
json_mode = output.lower() == "json"
|
|
177
200
|
try:
|
|
178
|
-
|
|
179
|
-
item
|
|
180
|
-
|
|
201
|
+
with spinner(
|
|
202
|
+
f"Fetching BOM for {item} ({revision or 'EFFECTIVE'})"
|
|
203
|
+
+ (" [recursive]" if recursive else "")
|
|
204
|
+
+ "…",
|
|
205
|
+
enabled=not json_mode,
|
|
206
|
+
):
|
|
207
|
+
lines = _client().get_bom(
|
|
208
|
+
item, revision, recursive=recursive, max_depth=max_depth
|
|
209
|
+
)
|
|
181
210
|
|
|
182
|
-
if
|
|
211
|
+
if json_mode:
|
|
183
212
|
print(json.dumps({"count": len(lines), "results": lines}, indent=2))
|
|
184
213
|
return
|
|
185
214
|
|
|
@@ -193,7 +222,7 @@ def bom(
|
|
|
193
222
|
|
|
194
223
|
for ln in lines:
|
|
195
224
|
lvl = int(ln.get("level", 0) or 0)
|
|
196
|
-
indent = " " * lvl
|
|
225
|
+
indent = " " * lvl
|
|
197
226
|
table.add_row(
|
|
198
227
|
str(ln.get("lineNumber") or ""),
|
|
199
228
|
str(ln.get("quantity") or ""),
|
|
@@ -233,14 +262,21 @@ def get_files(
|
|
|
233
262
|
help="Maximum recursion depth for --recursive (1 = only direct children).",
|
|
234
263
|
),
|
|
235
264
|
):
|
|
265
|
+
json_mode = False # this command prints file paths line-by-line (no JSON mode here)
|
|
236
266
|
try:
|
|
237
|
-
out_dir = out or Path(item)
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
267
|
+
out_dir = out or Path(item)
|
|
268
|
+
with spinner(
|
|
269
|
+
f"Downloading files for {item} ({revision or 'EFFECTIVE'})"
|
|
270
|
+
+ (" [recursive]" if recursive else "")
|
|
271
|
+
+ f" → {out_dir}…",
|
|
272
|
+
enabled=not json_mode,
|
|
273
|
+
):
|
|
274
|
+
if recursive:
|
|
275
|
+
paths = _client().download_files_recursive(
|
|
276
|
+
item, revision, out_dir=out_dir, max_depth=max_depth
|
|
277
|
+
)
|
|
278
|
+
else:
|
|
279
|
+
paths = _client().download_files(item, revision, out_dir=out_dir)
|
|
244
280
|
|
|
245
281
|
for p in paths:
|
|
246
282
|
print(str(p))
|
|
@@ -285,17 +321,18 @@ def upload_file(
|
|
|
285
321
|
"""If a file with the same filename exists: update its content (new edition).
|
|
286
322
|
Otherwise: create a new association on the WORKING revision (requires --edition)."""
|
|
287
323
|
try:
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
324
|
+
with spinner(f"Uploading {file.name} to {item}…", enabled=sys.stdout.isatty()):
|
|
325
|
+
result = _client().upload_file_to_working(
|
|
326
|
+
item,
|
|
327
|
+
file,
|
|
328
|
+
reference,
|
|
329
|
+
title=title,
|
|
330
|
+
category_name=category,
|
|
331
|
+
file_format=file_format,
|
|
332
|
+
description=description,
|
|
333
|
+
primary=primary,
|
|
334
|
+
edition=edition,
|
|
335
|
+
)
|
|
299
336
|
print(json.dumps(result, indent=2))
|
|
300
337
|
except requests.HTTPError as e:
|
|
301
338
|
typer.secho(f"Arena request failed: {e}", fg=typer.colors.RED, err=True)
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lr-gladiator
|
|
3
|
+
Version: 0.8.0
|
|
4
|
+
Summary: CLI and Python client for Arena PLM (app.bom.com): login, get revisions, list/download attachments, and upload to working revisions.
|
|
5
|
+
Author-email: Jonas Estberger <jonas.estberger@lumenradio.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: Arena,PLM,BOM,attachments,CLI
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: requests>=2.32
|
|
15
|
+
Requires-Dist: typer>=0.12
|
|
16
|
+
Requires-Dist: rich>=13.7
|
|
17
|
+
Requires-Dist: pydantic>=2.8
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: build>=1.2.1; extra == "dev"
|
|
20
|
+
Requires-Dist: twine>=5.1.1; extra == "dev"
|
|
21
|
+
Requires-Dist: wheel; extra == "dev"
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# gladiator-arena
|
|
25
|
+
|
|
26
|
+
CLI + Python client for interacting with the Arena PLM.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install lr-gladiator
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick start
|
|
35
|
+
|
|
36
|
+
### 1) Create `login.json`
|
|
37
|
+
|
|
38
|
+
Interactive login (prompts for username/password):
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
gladiator login
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Non-interactive (for CI/CD):
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
gladiator login --username "$ARENA_USERNAME" --password "$ARENA_PASSWORD" --ci
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
By default, this stores session details at:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
~/.config/gladiator/login.json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 2) Common commands
|
|
57
|
+
|
|
58
|
+
Get the latest approved revision for an item:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
gladiator latest-approved 890-1001
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
List all files on an item (defaults to the latest approved revision):
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
gladiator list-files 890-1001
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Output JSON instead of a table:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
gladiator list-files 890-1001 --format json
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
List the Bill of Materials (BOM) for an item:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
gladiator bom 890-1001
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Recursively expand subassemblies up to two levels deep:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
gladiator bom 890-1001 --recursive --max-depth 2
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Download attached files to a directory named after the article:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
gladiator get-files 890-1001
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Specify a different output directory:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
gladiator get-files 890-1001 --out downloads/
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Recursively download all files in the full BOM tree:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
gladiator get-files 890-1001 --recursive
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Upload or update a file on the working revision:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
gladiator upload-file 890-1001 ./datasheet.pdf --category "CAD Data" --title "Datasheet"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 3) Output control
|
|
113
|
+
|
|
114
|
+
Most commands support a JSON output mode.
|
|
115
|
+
Example:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
gladiator bom 890-1001 --output json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Example sessions
|
|
122
|
+
|
|
123
|
+
#### Human-readable
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
$ gladiator list-files 101-1031
|
|
127
|
+
Files for 101-1031 rev (latest approved)
|
|
128
|
+
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
|
|
129
|
+
┃ Name ┃ Size ┃ Checksum ┃
|
|
130
|
+
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
|
|
131
|
+
│ Drawing.pdf │ 12345 │ d41d8cd98f00b204e… │
|
|
132
|
+
└──────────────────────────────────────┴───────┴─────────────────────┘
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### JSON output
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
$ gladiator list-files 101-1031 --format json
|
|
139
|
+
{
|
|
140
|
+
"article": "101-1031",
|
|
141
|
+
"revision": "EFFECTIVE",
|
|
142
|
+
"files": [
|
|
143
|
+
{
|
|
144
|
+
"filename": "Drawing.pdf",
|
|
145
|
+
"size": 12345,
|
|
146
|
+
"checksum": "d41d8cd98f00b204e9800998ecf8427e"
|
|
147
|
+
}
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Programmatic use
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from gladiator import ArenaClient, load_config
|
|
156
|
+
|
|
157
|
+
client = ArenaClient(load_config())
|
|
158
|
+
rev = client.get_latest_approved_revision("890-1001")
|
|
159
|
+
files = client.list_files("890-1001", rev)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Development
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
python -m pip install -e .[dev]
|
|
166
|
+
python -m build
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## FAQ
|
|
170
|
+
|
|
171
|
+
- **Where is the config kept?**
|
|
172
|
+
`~/.config/gladiator/login.json` (override with `GLADIATOR_CONFIG`)
|
|
173
|
+
|
|
174
|
+
- **How do I run non-interactively?**
|
|
175
|
+
Pass `--ci` together with `--username` and `--password` (or use environment variables).
|
|
176
|
+
|
|
177
|
+
- **What does `--recursive` do?**
|
|
178
|
+
Expands subassemblies and downloads or lists all contained items up to the given `--max-depth`.
|
|
179
|
+
|
|
180
|
+
- **How does Gladiator handle authentication?**
|
|
181
|
+
It performs a `/login` call and stores the resulting `arenaSessionId` for reuse. If it expires, re-run `gladiator login`.
|
lr_gladiator-0.7.0/PKG-INFO
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: lr-gladiator
|
|
3
|
-
Version: 0.7.0
|
|
4
|
-
Summary: CLI and Python client for Arena PLM (app.bom.com): login, get revisions, list/download attachments, and upload to working revisions.
|
|
5
|
-
Author-email: Jonas Estberger <jonas.estberger@lumenradio.com>
|
|
6
|
-
License: MIT
|
|
7
|
-
Keywords: Arena,PLM,BOM,attachments,CLI
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
-
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.9
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
License-File: LICENSE
|
|
14
|
-
Requires-Dist: requests>=2.32
|
|
15
|
-
Requires-Dist: typer>=0.12
|
|
16
|
-
Requires-Dist: rich>=13.7
|
|
17
|
-
Requires-Dist: pydantic>=2.8
|
|
18
|
-
Provides-Extra: dev
|
|
19
|
-
Requires-Dist: build>=1.2.1; extra == "dev"
|
|
20
|
-
Requires-Dist: twine>=5.1.1; extra == "dev"
|
|
21
|
-
Requires-Dist: wheel; extra == "dev"
|
|
22
|
-
Dynamic: license-file
|
|
23
|
-
|
|
24
|
-
# gladiator-arena
|
|
25
|
-
|
|
26
|
-
CLI + Python client for interacting with the Arena PLM.
|
|
27
|
-
|
|
28
|
-
## Install
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
pip install lr-gladiator
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Quick start
|
|
35
|
-
|
|
36
|
-
### 1) Create `login.json`
|
|
37
|
-
|
|
38
|
-
Interactive:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
gladiator login
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
`login.json` is stored at `~/.config/gladiator/login.json` by default.
|
|
45
|
-
|
|
46
|
-
### 2) Queries
|
|
47
|
-
|
|
48
|
-
Get latest approved revision for an item:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
gladiator latest-approved ABC-1234
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
List files on an item (defaults to latest approved):
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
gladiator list-files ABC-1234
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
Download files:
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
gladiator get-files ABC-1234 --out downloads/
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
Upload a file to the working revision
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
gladiator upload-file ABC-1234 ./datasheet.pdf --reference datasheet
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## Programmatic use
|
|
73
|
-
|
|
74
|
-
```python
|
|
75
|
-
from gladiator import ArenaClient, load_config
|
|
76
|
-
client = ArenaClient(load_config())
|
|
77
|
-
rev = client.get_latest_approved_revision("ABC-1234")
|
|
78
|
-
files = client.list_files("ABC-1234", rev)
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## Development
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
python -m pip install -e .[dev]
|
|
85
|
-
python -m build
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## FAQ
|
|
89
|
-
|
|
90
|
-
- **Where is the config kept?** `~/.config/gladiator/login.json` (override via `GLADIATOR_CONFIG`).
|
lr_gladiator-0.7.0/README.md
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
# gladiator-arena
|
|
2
|
-
|
|
3
|
-
CLI + Python client for interacting with the Arena PLM.
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
pip install lr-gladiator
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Quick start
|
|
12
|
-
|
|
13
|
-
### 1) Create `login.json`
|
|
14
|
-
|
|
15
|
-
Interactive:
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
gladiator login
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
`login.json` is stored at `~/.config/gladiator/login.json` by default.
|
|
22
|
-
|
|
23
|
-
### 2) Queries
|
|
24
|
-
|
|
25
|
-
Get latest approved revision for an item:
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
gladiator latest-approved ABC-1234
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
List files on an item (defaults to latest approved):
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
gladiator list-files ABC-1234
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Download files:
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
gladiator get-files ABC-1234 --out downloads/
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Upload a file to the working revision
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
gladiator upload-file ABC-1234 ./datasheet.pdf --reference datasheet
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Programmatic use
|
|
50
|
-
|
|
51
|
-
```python
|
|
52
|
-
from gladiator import ArenaClient, load_config
|
|
53
|
-
client = ArenaClient(load_config())
|
|
54
|
-
rev = client.get_latest_approved_revision("ABC-1234")
|
|
55
|
-
files = client.list_files("ABC-1234", rev)
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Development
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
python -m pip install -e .[dev]
|
|
62
|
-
python -m build
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## FAQ
|
|
66
|
-
|
|
67
|
-
- **Where is the config kept?** `~/.config/gladiator/login.json` (override via `GLADIATOR_CONFIG`).
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: lr-gladiator
|
|
3
|
-
Version: 0.7.0
|
|
4
|
-
Summary: CLI and Python client for Arena PLM (app.bom.com): login, get revisions, list/download attachments, and upload to working revisions.
|
|
5
|
-
Author-email: Jonas Estberger <jonas.estberger@lumenradio.com>
|
|
6
|
-
License: MIT
|
|
7
|
-
Keywords: Arena,PLM,BOM,attachments,CLI
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
-
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.9
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
License-File: LICENSE
|
|
14
|
-
Requires-Dist: requests>=2.32
|
|
15
|
-
Requires-Dist: typer>=0.12
|
|
16
|
-
Requires-Dist: rich>=13.7
|
|
17
|
-
Requires-Dist: pydantic>=2.8
|
|
18
|
-
Provides-Extra: dev
|
|
19
|
-
Requires-Dist: build>=1.2.1; extra == "dev"
|
|
20
|
-
Requires-Dist: twine>=5.1.1; extra == "dev"
|
|
21
|
-
Requires-Dist: wheel; extra == "dev"
|
|
22
|
-
Dynamic: license-file
|
|
23
|
-
|
|
24
|
-
# gladiator-arena
|
|
25
|
-
|
|
26
|
-
CLI + Python client for interacting with the Arena PLM.
|
|
27
|
-
|
|
28
|
-
## Install
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
pip install lr-gladiator
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Quick start
|
|
35
|
-
|
|
36
|
-
### 1) Create `login.json`
|
|
37
|
-
|
|
38
|
-
Interactive:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
gladiator login
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
`login.json` is stored at `~/.config/gladiator/login.json` by default.
|
|
45
|
-
|
|
46
|
-
### 2) Queries
|
|
47
|
-
|
|
48
|
-
Get latest approved revision for an item:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
gladiator latest-approved ABC-1234
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
List files on an item (defaults to latest approved):
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
gladiator list-files ABC-1234
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
Download files:
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
gladiator get-files ABC-1234 --out downloads/
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
Upload a file to the working revision
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
gladiator upload-file ABC-1234 ./datasheet.pdf --reference datasheet
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## Programmatic use
|
|
73
|
-
|
|
74
|
-
```python
|
|
75
|
-
from gladiator import ArenaClient, load_config
|
|
76
|
-
client = ArenaClient(load_config())
|
|
77
|
-
rev = client.get_latest_approved_revision("ABC-1234")
|
|
78
|
-
files = client.list_files("ABC-1234", rev)
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## Development
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
python -m pip install -e .[dev]
|
|
85
|
-
python -m build
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## FAQ
|
|
89
|
-
|
|
90
|
-
- **Where is the config kept?** `~/.config/gladiator/login.json` (override via `GLADIATOR_CONFIG`).
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|