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 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.
@@ -0,0 +1,4 @@
1
+ include README.md
2
+ include LICENSE
3
+ recursive-include arty_mc *.py
4
+ recursive-include media *.png
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
+ ![Python](https://img.shields.io/badge/python-3.9+-blue.svg)
34
+ ![License](https://img.shields.io/badge/license-MIT-green.svg)
35
+ ![Platform](https://img.shields.io/badge/platform-linux-lightgrey.svg)
36
+ ![Status](https://img.shields.io/badge/status-experimental-orange.svg)
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
+ ![arty-mc_screenshot](/media/arty-mc1.png)
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
+ [![Demo Cast](https://asciinema.org/a/WHdbkcCi2WBvoTrX.svg)](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
+
@@ -0,0 +1,274 @@
1
+ # arty-mc
2
+
3
+ ![Python](https://img.shields.io/badge/python-3.9+-blue.svg)
4
+ ![License](https://img.shields.io/badge/license-MIT-green.svg)
5
+ ![Platform](https://img.shields.io/badge/platform-linux-lightgrey.svg)
6
+ ![Status](https://img.shields.io/badge/status-experimental-orange.svg)
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
+ ![arty-mc_screenshot](/media/arty-mc1.png)
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
+ [![Demo Cast](https://asciinema.org/a/WHdbkcCi2WBvoTrX.svg)](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,3 @@
1
+ from .arty_mc import main
2
+
3
+ __all__ = ["main"]
@@ -0,0 +1,4 @@
1
+ from .arty_mc import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
@@ -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