arty-mc 0.1.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.
- arty_mc-0.1.0/LICENSE +21 -0
- arty_mc-0.1.0/MANIFEST.in +4 -0
- arty_mc-0.1.0/PKG-INFO +304 -0
- arty_mc-0.1.0/README.md +274 -0
- arty_mc-0.1.0/arty_mc/__init__.py +3 -0
- arty_mc-0.1.0/arty_mc/__main__.py +4 -0
- arty_mc-0.1.0/arty_mc/arty_mc.py +40 -0
- arty_mc-0.1.0/arty_mc/auth.py +18 -0
- arty_mc-0.1.0/arty_mc/config.py +42 -0
- arty_mc-0.1.0/arty_mc/core/__init__.py +0 -0
- arty_mc-0.1.0/arty_mc/core/api_client.py +53 -0
- arty_mc-0.1.0/arty_mc/core/artifactory_fs.py +130 -0
- arty_mc-0.1.0/arty_mc/core/local_fs.py +109 -0
- arty_mc-0.1.0/arty_mc/core/transfers.py +259 -0
- arty_mc-0.1.0/arty_mc/ui/__init__.py +0 -0
- arty_mc-0.1.0/arty_mc/ui/commander_screen.py +295 -0
- arty_mc-0.1.0/arty_mc/ui/confirm_dialog.py +67 -0
- arty_mc-0.1.0/arty_mc/ui/delete_panel.py +45 -0
- arty_mc-0.1.0/arty_mc/ui/file_table.py +56 -0
- arty_mc-0.1.0/arty_mc/ui/filter_bar.py +30 -0
- arty_mc-0.1.0/arty_mc/ui/path_line.py +20 -0
- arty_mc-0.1.0/arty_mc/ui/transfer_panel.py +85 -0
- arty_mc-0.1.0/arty_mc.egg-info/PKG-INFO +304 -0
- arty_mc-0.1.0/arty_mc.egg-info/SOURCES.txt +30 -0
- arty_mc-0.1.0/arty_mc.egg-info/dependency_links.txt +1 -0
- arty_mc-0.1.0/arty_mc.egg-info/entry_points.txt +2 -0
- arty_mc-0.1.0/arty_mc.egg-info/requires.txt +4 -0
- arty_mc-0.1.0/arty_mc.egg-info/top_level.txt +1 -0
- arty_mc-0.1.0/media/arty-mc1.png +0 -0
- arty_mc-0.1.0/pyproject.toml +3 -0
- arty_mc-0.1.0/setup.cfg +4 -0
- arty_mc-0.1.0/setup.py +32 -0
arty_mc-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tino Waldner
|
|
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.
|
arty_mc-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: arty-mc
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Dual-pane terminal file manager for Artifactory
|
|
5
|
+
Home-page: https://github.com/tino-waldner/arty-mc
|
|
6
|
+
Author: Tino Waldner
|
|
7
|
+
Author-email: tino.waldner@gmail.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Topic :: Utilities
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Requires-Python: >=3.9
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: textual
|
|
17
|
+
Requires-Dist: requests
|
|
18
|
+
Requires-Dist: dohq-artifactory
|
|
19
|
+
Requires-Dist: pyyaml
|
|
20
|
+
Dynamic: author
|
|
21
|
+
Dynamic: author-email
|
|
22
|
+
Dynamic: classifier
|
|
23
|
+
Dynamic: description
|
|
24
|
+
Dynamic: description-content-type
|
|
25
|
+
Dynamic: home-page
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
Dynamic: requires-dist
|
|
28
|
+
Dynamic: requires-python
|
|
29
|
+
Dynamic: summary
|
|
30
|
+
|
|
31
|
+
# arty-mc
|
|
32
|
+
|
|
33
|
+

|
|
34
|
+

|
|
35
|
+

|
|
36
|
+

|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
o o o o
|
|
40
|
+
<|> <|> <|\ /|>
|
|
41
|
+
/ \ < > / \\o o// \
|
|
42
|
+
o/ \o \o__ __o | o o \o/ v\ /v \o/ __o__
|
|
43
|
+
<|__ __|> | |> o__/_ <|> <|> _\__o__ | <\/> | /> \
|
|
44
|
+
/ \ / \ < > | < > < > \ / \ / \ o/
|
|
45
|
+
o/ \o \o/ | \o o/ \o/ \o/ <|
|
|
46
|
+
/v v\ | o v\ /v | | \\
|
|
47
|
+
/> <\ / \ <\__ <\/> / \ / \ _\o__</
|
|
48
|
+
/
|
|
49
|
+
o
|
|
50
|
+
__/>
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**arty-mc** is a **Python package** providing a terminal file manager for JFrog Artifactory.
|
|
55
|
+
|
|
56
|
+
It provides a **dual-pane interface similar to Midnight Commander**, allowing you to **browse, filter, copy and delete** files and folders between **the local filesystem and Artifactory repositories** directly from the terminal.
|
|
57
|
+
|
|
58
|
+
It uses **Textual** for the terminal interface and **dohq-artifactory** for interacting with Artifactory repositories.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
# Why arty-mc?
|
|
63
|
+
|
|
64
|
+
Managing artifacts in Artifactory is often done through the web UI, generic tools like `curl` or the `jf-cli`.
|
|
65
|
+
For developers who prefer working directly in the terminal, this can be inconvenient.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
# Features
|
|
70
|
+
|
|
71
|
+
* Dual-pane terminal interface
|
|
72
|
+
* Browse/Filer local filesystem and Artifactory repositories
|
|
73
|
+
* Copy files between panes
|
|
74
|
+
* Delete artifacts
|
|
75
|
+
* Simple YAML configuration
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
# Screenshot
|
|
80
|
+

|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
# Requirements
|
|
85
|
+
|
|
86
|
+
* Python **3.9+**
|
|
87
|
+
* Access to an **Artifactory server**
|
|
88
|
+
* Artifactory **API token**
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
# Installation
|
|
93
|
+
|
|
94
|
+
## 1. Clone the Repository
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
git clone https://github.com/tino-waldner/arty-mc.git
|
|
98
|
+
cd arty-mc
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 2. Python Package
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
mkdir .venv
|
|
107
|
+
python3 -m venv .venv
|
|
108
|
+
source .venv/bin/activate
|
|
109
|
+
pip install .
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 3. Create Configuration File
|
|
115
|
+
|
|
116
|
+
Create a configuration file in your home directory:
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
~/.arty-mc.yml
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Example configuration:
|
|
123
|
+
|
|
124
|
+
```yaml
|
|
125
|
+
server: https://artifactory.company.com/artifactory
|
|
126
|
+
user: myuser
|
|
127
|
+
token: ********************************************
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Configuration Fields
|
|
131
|
+
|
|
132
|
+
| Field | Description |
|
|
133
|
+
| ------ | ---------------------------------- |
|
|
134
|
+
| server | Base URL of the Artifactory server |
|
|
135
|
+
| user | Artifactory username |
|
|
136
|
+
| token | Artifactory API token |
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
# Running arty-mc
|
|
141
|
+
|
|
142
|
+
Run the tool directly:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
python -m arty_mc <repository>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Example:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
python -m arty_mc libs-release-local
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
This starts the **dual-pane interface** where you can browse your local filesystem and the selected repository.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
# Typical Workflow
|
|
159
|
+
|
|
160
|
+
1. Start **arty-mc** with a repository
|
|
161
|
+
2. Navigate the **local filesystem** in one pane
|
|
162
|
+
3. Browse the **Artifactory repository** in the other pane
|
|
163
|
+
4. Copy files between panes
|
|
164
|
+
5. Delete artifacts if needed
|
|
165
|
+
|
|
166
|
+
⚠ **Warning:** Deleting artifacts from repositories may be irreversible.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
# Keyboard Shortcuts
|
|
171
|
+
|
|
172
|
+
| Key | Action |
|
|
173
|
+
| ----- | ---------------- |
|
|
174
|
+
| ↑ ↓ | Navigate |
|
|
175
|
+
| Enter | Open directory |
|
|
176
|
+
| Tab | Switch pane |
|
|
177
|
+
| F2 | Cancel Operation |
|
|
178
|
+
| F5 | Copy |
|
|
179
|
+
| F8 | Delete |
|
|
180
|
+
| F10 | Quit |
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
# Building an Executable with Pyinstaller
|
|
185
|
+
|
|
186
|
+
You can build a binary using **PyInstaller**.
|
|
187
|
+
|
|
188
|
+
Install PyInstaller:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
pip install pyinstaller
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Build the binary:
|
|
195
|
+
|
|
196
|
+
**-—onefile:** slower startup caused by runtime extraction
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
pyinstaller --onefile --distpath dist --name arty-mc arty_mc/arty_mc.py
|
|
200
|
+
```
|
|
201
|
+
**-—onedir:** faster after initial startup
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
pyinstaller --onedir --distpath dist --name arty-mc arty_mc/arty_mc.py
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The compiled executable will appear in:
|
|
208
|
+
|
|
209
|
+
```text
|
|
210
|
+
dist/arty-mc/
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
You can run it without a Python environment.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
# Packaging and uploading the arty-mc Python library
|
|
218
|
+
|
|
219
|
+
You can also build this python package
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
git clone https://github.com/tino-waldner/arty-mc.git
|
|
223
|
+
cd arty-mc
|
|
224
|
+
mkdir .venv
|
|
225
|
+
python3 -m venv .venv
|
|
226
|
+
source .venv/bin/activate
|
|
227
|
+
pip install build twine
|
|
228
|
+
python -m build
|
|
229
|
+
twine check dist/*
|
|
230
|
+
twine upload dist/*
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
# Building an Executable with Pyinstaller
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
mkdir .venv
|
|
239
|
+
python3 -m venv .venv
|
|
240
|
+
source .venv/bin/activate
|
|
241
|
+
pip install -r requirements.txt
|
|
242
|
+
```
|
|
243
|
+
Install PyInstaller:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
pip install pyinstaller
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Build the binary:
|
|
250
|
+
|
|
251
|
+
**-—onefile:** slower startup caused by runtime extraction
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
pyinstaller --onefile --distpath dist --name arty-mc arty_mc/arty_mc.py
|
|
255
|
+
```
|
|
256
|
+
**-—onedir:** faster after initial startup
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
pyinstaller --onedir --distpath dist --name arty-mc arty_mc/arty_mc.py
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
The compiled executable will appear in:
|
|
263
|
+
|
|
264
|
+
```text
|
|
265
|
+
arty_mc/dist/arty-mc/
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
You can run it without a Python environment.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
# Security Notes
|
|
273
|
+
|
|
274
|
+
* Do **not** commit your `.arty-mc.yml` file
|
|
275
|
+
* Protect your **API token**
|
|
276
|
+
* Prefer **API tokens instead of passwords**
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
# Demo
|
|
281
|
+
|
|
282
|
+
[](https://asciinema.org/a/WHdbkcCi2WBvoTrX)
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
# Disclaimer
|
|
287
|
+
|
|
288
|
+
This software is provided **"as is" without warranty of any kind**.
|
|
289
|
+
|
|
290
|
+
The tool may contain **bugs or incomplete functionality** and should be used **at your own risk**.
|
|
291
|
+
The author assumes **no responsibility or liability for any damage, data loss, system malfunction, or unintended modifications** caused by the use of this software.
|
|
292
|
+
|
|
293
|
+
Always verify actions such as **uploading, deleting, or overwriting artifacts**, especially when working with production repositories.
|
|
294
|
+
|
|
295
|
+
This project is **not affiliated with or endorsed by JFrog**.
|
|
296
|
+
|
|
297
|
+
JFrog and Artifactory are trademarks of JFrog Ltd.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
# License
|
|
302
|
+
|
|
303
|
+
MIT License
|
|
304
|
+
|
arty_mc-0.1.0/README.md
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# arty-mc
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
```text
|
|
9
|
+
o o o o
|
|
10
|
+
<|> <|> <|\ /|>
|
|
11
|
+
/ \ < > / \\o o// \
|
|
12
|
+
o/ \o \o__ __o | o o \o/ v\ /v \o/ __o__
|
|
13
|
+
<|__ __|> | |> o__/_ <|> <|> _\__o__ | <\/> | /> \
|
|
14
|
+
/ \ / \ < > | < > < > \ / \ / \ o/
|
|
15
|
+
o/ \o \o/ | \o o/ \o/ \o/ <|
|
|
16
|
+
/v v\ | o v\ /v | | \\
|
|
17
|
+
/> <\ / \ <\__ <\/> / \ / \ _\o__</
|
|
18
|
+
/
|
|
19
|
+
o
|
|
20
|
+
__/>
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**arty-mc** is a **Python package** providing a terminal file manager for JFrog Artifactory.
|
|
25
|
+
|
|
26
|
+
It provides a **dual-pane interface similar to Midnight Commander**, allowing you to **browse, filter, copy and delete** files and folders between **the local filesystem and Artifactory repositories** directly from the terminal.
|
|
27
|
+
|
|
28
|
+
It uses **Textual** for the terminal interface and **dohq-artifactory** for interacting with Artifactory repositories.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
# Why arty-mc?
|
|
33
|
+
|
|
34
|
+
Managing artifacts in Artifactory is often done through the web UI, generic tools like `curl` or the `jf-cli`.
|
|
35
|
+
For developers who prefer working directly in the terminal, this can be inconvenient.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
# Features
|
|
40
|
+
|
|
41
|
+
* Dual-pane terminal interface
|
|
42
|
+
* Browse/Filer local filesystem and Artifactory repositories
|
|
43
|
+
* Copy files between panes
|
|
44
|
+
* Delete artifacts
|
|
45
|
+
* Simple YAML configuration
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
# Screenshot
|
|
50
|
+

|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
# Requirements
|
|
55
|
+
|
|
56
|
+
* Python **3.9+**
|
|
57
|
+
* Access to an **Artifactory server**
|
|
58
|
+
* Artifactory **API token**
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
# Installation
|
|
63
|
+
|
|
64
|
+
## 1. Clone the Repository
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
git clone https://github.com/tino-waldner/arty-mc.git
|
|
68
|
+
cd arty-mc
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 2. Python Package
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
mkdir .venv
|
|
77
|
+
python3 -m venv .venv
|
|
78
|
+
source .venv/bin/activate
|
|
79
|
+
pip install .
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 3. Create Configuration File
|
|
85
|
+
|
|
86
|
+
Create a configuration file in your home directory:
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
~/.arty-mc.yml
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Example configuration:
|
|
93
|
+
|
|
94
|
+
```yaml
|
|
95
|
+
server: https://artifactory.company.com/artifactory
|
|
96
|
+
user: myuser
|
|
97
|
+
token: ********************************************
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Configuration Fields
|
|
101
|
+
|
|
102
|
+
| Field | Description |
|
|
103
|
+
| ------ | ---------------------------------- |
|
|
104
|
+
| server | Base URL of the Artifactory server |
|
|
105
|
+
| user | Artifactory username |
|
|
106
|
+
| token | Artifactory API token |
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
# Running arty-mc
|
|
111
|
+
|
|
112
|
+
Run the tool directly:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
python -m arty_mc <repository>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Example:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
python -m arty_mc libs-release-local
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
This starts the **dual-pane interface** where you can browse your local filesystem and the selected repository.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
# Typical Workflow
|
|
129
|
+
|
|
130
|
+
1. Start **arty-mc** with a repository
|
|
131
|
+
2. Navigate the **local filesystem** in one pane
|
|
132
|
+
3. Browse the **Artifactory repository** in the other pane
|
|
133
|
+
4. Copy files between panes
|
|
134
|
+
5. Delete artifacts if needed
|
|
135
|
+
|
|
136
|
+
⚠ **Warning:** Deleting artifacts from repositories may be irreversible.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
# Keyboard Shortcuts
|
|
141
|
+
|
|
142
|
+
| Key | Action |
|
|
143
|
+
| ----- | ---------------- |
|
|
144
|
+
| ↑ ↓ | Navigate |
|
|
145
|
+
| Enter | Open directory |
|
|
146
|
+
| Tab | Switch pane |
|
|
147
|
+
| F2 | Cancel Operation |
|
|
148
|
+
| F5 | Copy |
|
|
149
|
+
| F8 | Delete |
|
|
150
|
+
| F10 | Quit |
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
# Building an Executable with Pyinstaller
|
|
155
|
+
|
|
156
|
+
You can build a binary using **PyInstaller**.
|
|
157
|
+
|
|
158
|
+
Install PyInstaller:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
pip install pyinstaller
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Build the binary:
|
|
165
|
+
|
|
166
|
+
**-—onefile:** slower startup caused by runtime extraction
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
pyinstaller --onefile --distpath dist --name arty-mc arty_mc/arty_mc.py
|
|
170
|
+
```
|
|
171
|
+
**-—onedir:** faster after initial startup
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
pyinstaller --onedir --distpath dist --name arty-mc arty_mc/arty_mc.py
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
The compiled executable will appear in:
|
|
178
|
+
|
|
179
|
+
```text
|
|
180
|
+
dist/arty-mc/
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
You can run it without a Python environment.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
# Packaging and uploading the arty-mc Python library
|
|
188
|
+
|
|
189
|
+
You can also build this python package
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
git clone https://github.com/tino-waldner/arty-mc.git
|
|
193
|
+
cd arty-mc
|
|
194
|
+
mkdir .venv
|
|
195
|
+
python3 -m venv .venv
|
|
196
|
+
source .venv/bin/activate
|
|
197
|
+
pip install build twine
|
|
198
|
+
python -m build
|
|
199
|
+
twine check dist/*
|
|
200
|
+
twine upload dist/*
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
# Building an Executable with Pyinstaller
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
mkdir .venv
|
|
209
|
+
python3 -m venv .venv
|
|
210
|
+
source .venv/bin/activate
|
|
211
|
+
pip install -r requirements.txt
|
|
212
|
+
```
|
|
213
|
+
Install PyInstaller:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
pip install pyinstaller
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Build the binary:
|
|
220
|
+
|
|
221
|
+
**-—onefile:** slower startup caused by runtime extraction
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
pyinstaller --onefile --distpath dist --name arty-mc arty_mc/arty_mc.py
|
|
225
|
+
```
|
|
226
|
+
**-—onedir:** faster after initial startup
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
pyinstaller --onedir --distpath dist --name arty-mc arty_mc/arty_mc.py
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
The compiled executable will appear in:
|
|
233
|
+
|
|
234
|
+
```text
|
|
235
|
+
arty_mc/dist/arty-mc/
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
You can run it without a Python environment.
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
# Security Notes
|
|
243
|
+
|
|
244
|
+
* Do **not** commit your `.arty-mc.yml` file
|
|
245
|
+
* Protect your **API token**
|
|
246
|
+
* Prefer **API tokens instead of passwords**
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
# Demo
|
|
251
|
+
|
|
252
|
+
[](https://asciinema.org/a/WHdbkcCi2WBvoTrX)
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
# Disclaimer
|
|
257
|
+
|
|
258
|
+
This software is provided **"as is" without warranty of any kind**.
|
|
259
|
+
|
|
260
|
+
The tool may contain **bugs or incomplete functionality** and should be used **at your own risk**.
|
|
261
|
+
The author assumes **no responsibility or liability for any damage, data loss, system malfunction, or unintended modifications** caused by the use of this software.
|
|
262
|
+
|
|
263
|
+
Always verify actions such as **uploading, deleting, or overwriting artifacts**, especially when working with production repositories.
|
|
264
|
+
|
|
265
|
+
This project is **not affiliated with or endorsed by JFrog**.
|
|
266
|
+
|
|
267
|
+
JFrog and Artifactory are trademarks of JFrog Ltd.
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
# License
|
|
272
|
+
|
|
273
|
+
MIT License
|
|
274
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
from textual.app import App # type: ignore
|
|
4
|
+
|
|
5
|
+
from arty_mc.config import load_config
|
|
6
|
+
from arty_mc.ui.commander_screen import CommanderScreen
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ArtyMc(App):
|
|
10
|
+
TITLE = "Arty-Mc"
|
|
11
|
+
|
|
12
|
+
def __init__(self, repo):
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.repo = repo
|
|
15
|
+
|
|
16
|
+
def on_mount(self):
|
|
17
|
+
config = load_config()
|
|
18
|
+
config["default_repo"] = self.repo
|
|
19
|
+
self.push_screen(CommanderScreen(config))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def print_usage():
|
|
23
|
+
print("Usage:")
|
|
24
|
+
print(" arty-mc <repository>")
|
|
25
|
+
print("Options:")
|
|
26
|
+
print(" --help Show this help message")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def main():
|
|
30
|
+
if len(sys.argv) < 2 or sys.argv[1] in ("-h", "--help"):
|
|
31
|
+
print_usage()
|
|
32
|
+
sys.exit(0)
|
|
33
|
+
|
|
34
|
+
repo = sys.argv[1]
|
|
35
|
+
app = ArtyMc(repo)
|
|
36
|
+
app.run()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
main()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import requests # type: ignore
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class AuthSession:
|
|
5
|
+
def __init__(self, base, user, token):
|
|
6
|
+
self.base = base.rstrip("/")
|
|
7
|
+
self.session = requests.Session()
|
|
8
|
+
self.session.auth = (user, token)
|
|
9
|
+
|
|
10
|
+
def get(self, url):
|
|
11
|
+
r = self.session.get(self.base + url)
|
|
12
|
+
r.raise_for_status()
|
|
13
|
+
return r.json()
|
|
14
|
+
|
|
15
|
+
def post(self, url, data):
|
|
16
|
+
r = self.session.post(self.base + url, data=data)
|
|
17
|
+
r.raise_for_status()
|
|
18
|
+
return r.json()
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import yaml # type: ignore
|
|
5
|
+
|
|
6
|
+
DEFAULT_CONFIG = {
|
|
7
|
+
"server": None,
|
|
8
|
+
"user": None,
|
|
9
|
+
"token": None,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def is_valid_url(url: str) -> bool:
|
|
14
|
+
pattern = re.compile(
|
|
15
|
+
r"^(https?://)"
|
|
16
|
+
r"(([a-zA-Z0-9.-]+)|"
|
|
17
|
+
r"(\d{1,3}(\.\d{1,3}){3}))"
|
|
18
|
+
r"(:\d+)?"
|
|
19
|
+
r"(/.*)?$"
|
|
20
|
+
)
|
|
21
|
+
return bool(pattern.match(url))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def load_config():
|
|
25
|
+
path = Path.home() / ".arty-mc.yml"
|
|
26
|
+
|
|
27
|
+
if not path.exists():
|
|
28
|
+
raise RuntimeError("Config file missing: ~/.arty-mc.yml")
|
|
29
|
+
|
|
30
|
+
with open(path) as f:
|
|
31
|
+
data = yaml.safe_load(f)
|
|
32
|
+
|
|
33
|
+
cfg = {**DEFAULT_CONFIG, **data}
|
|
34
|
+
|
|
35
|
+
server = cfg.get("server")
|
|
36
|
+
if not server:
|
|
37
|
+
raise RuntimeError("Config error: 'server' not defined")
|
|
38
|
+
|
|
39
|
+
if not is_valid_url(server):
|
|
40
|
+
raise RuntimeError(f"Config error: server '{server}' is not a valid URL.")
|
|
41
|
+
|
|
42
|
+
return cfg
|