| Hash | Commit message | Author | Date | Files | + | - |
1 | commit d2fe27f72c91445605eaef0d5a4f445c9904935c |
2 | Author: Connor Etherington <[email protected]> |
3 | Date: Tue Aug 22 14:34:20 2023 +0200 |
4 | |
5 | Auto-Commit Update - 20230822 |
6 | --- |
7 | PKGBUILD | 2 +- |
8 | README.md | 2 +- |
9 | build/lib/ptrack/__init__.py | 16 +++ |
10 | build/lib/ptrack/main.py | 207 +++++++++++++++++++++++++++++++++++ |
11 | build/lib/ptrack/methods.py | 136 +++++++++++++++++++++++ |
12 | dist/ptrack-0.2.2-py3-none-any.whl | Bin 0 -> 6551 bytes |
13 | dist/ptrack-0.2.2.tar.gz | Bin 0 -> 6568 bytes |
14 | ptrack.egg-info/PKG-INFO | 7 ++ |
15 | ptrack.egg-info/SOURCES.txt | 12 ++ |
16 | ptrack.egg-info/dependency_links.txt | 1 + |
17 | ptrack.egg-info/entry_points.txt | 5 + |
18 | ptrack.egg-info/requires.txt | 6 + |
19 | ptrack.egg-info/top_level.txt | 1 + |
20 | ptrack/__init__.py | 4 +- |
21 | ptrack/main.py | 21 ++-- |
22 | ptrack/methods.py | 8 +- |
23 | recipe/meta.yaml | 2 +- |
24 | setup.py | 4 +- |
25 | 18 files changed, 415 insertions(+), 19 deletions(-) |
26 | |
27 | diff --git a/PKGBUILD b/PKGBUILD |
28 | index 9cbf2c1..024da0a 100644 |
29 | --- a/PKGBUILD |
30 | +++ b/PKGBUILD |
31 | @@ -1,7 +1,7 @@ |
32 | # Maintainer: Connor Etherington <[email protected]> |
33 | # --- |
34 | pkgname=ptrack |
35 | -pkgver=0.2.1 |
36 | +pkgver=0.2.2 |
37 | pkgrel=1 |
38 | pkgdesc="A simple CLI utility for asthetically tracking progress when copying, moving or downloading files." |
39 | arch=(x86_64) |
40 | diff --git a/README.md b/README.md |
41 | index e2cc0aa..f1130dd 100644 |
42 | --- a/README.md |
43 | +++ b/README.md |
44 | @@ -3,7 +3,7 @@ |
45 | ### Welcome to ptrack, a powerful and user-friendly CLI utility for tracking the progress of your file operations. |
46 | ### Designed to be as concise, efficient and performance-optimized, ptrack works swiftly and accurately, while providing insight into the progress of the task at hand. |
47 | |
48 | -*Version: 0.2.1* |
49 | +*Version: 0.2.2* |
50 | |
51 | *** |
52 | |
53 | diff --git a/build/lib/ptrack/__init__.py b/build/lib/ptrack/__init__.py |
54 | new file mode 100644 |
55 | index 0000000..112f15e |
56 | --- /dev/null |
57 | +++ b/build/lib/ptrack/__init__.py |
58 | @@ -0,0 +1,16 @@ |
59 | +import argparse |
60 | +version="0.2.2" |
61 | + |
62 | +parser = argparse.ArgumentParser(description='A simple CLI utility for asthetically tracking progress when copying or moving files.') |
63 | +parser.add_argument('-v', '--verbose', action='store_true', help='verbose output') |
64 | +parser.add_argument('-c', '--copy', action='store_true', help='copy files (You can use `ptc` instead of `ptrack -c`)') |
65 | +parser.add_argument('-m', '--move', action='store_true', help='move files (You can use `ptm` instead of `ptrack -m`)') |
66 | +parser.add_argument('-d', '--download', action='store_true', help='download files (You can use `ptd` instead of `ptrack -d`)') |
67 | +parser.add_argument('-V', '--version', action='version', version='%(prog)s' + version) |
68 | + |
69 | +args, unknown = parser.parse_known_args() |
70 | + |
71 | +verbose = args.verbose |
72 | +copy = args.copy |
73 | +move = args.move |
74 | +download = args.download |
75 | diff --git a/build/lib/ptrack/main.py b/build/lib/ptrack/main.py |
76 | new file mode 100644 |
77 | index 0000000..48523fa |
78 | --- /dev/null |
79 | +++ b/build/lib/ptrack/main.py |
80 | @@ -0,0 +1,207 @@ |
81 | +import os |
82 | +import re |
83 | +import sys |
84 | +import ptrack |
85 | +from ptrack.methods import format_file_size, regular_copy, verbose_copy, hlp, getTotalSize, CustomFileSizeColumn |
86 | +from rich.progress import Progress, BarColumn, TextColumn, TimeRemainingColumn, FileSizeColumn |
87 | +from rich.console import Console |
88 | +from datetime import timedelta |
89 | +import shutil |
90 | +import requests |
91 | +import validators |
92 | + |
93 | +verbose = ptrack.verbose |
94 | +argCopy = ptrack.copy |
95 | +argMove = ptrack.move |
96 | +argDownload = ptrack.download |
97 | + |
98 | + |
99 | +def run(process): |
100 | + console = Console() |
101 | + |
102 | + if len(sys.argv) < 3: |
103 | + hlp() |
104 | + if process == "Copying": |
105 | + console.print("[bold cyan]Usage: ptc [OPTIONS] SOURCE... DESTINATION[/bold cyan]") |
106 | + elif process == "Moving": |
107 | + console.print("[bold cyan]Usage: ptm [OPTIONS] SOURCE... DESTINATION[/bold cyan]") |
108 | + sys.exit(1) |
109 | + |
110 | + src_paths = sys.argv[1:-1] |
111 | + dst = sys.argv[-1] |
112 | + srcPaths = [] |
113 | + |
114 | + for path in src_paths: |
115 | + if path.endswith('/'): |
116 | + path = path[:-1] |
117 | + srcPaths.append(path) |
118 | + |
119 | + if os.path.isdir(dst): |
120 | + dst_dir = dst |
121 | + new_name = None |
122 | + else: |
123 | + dst_dir = os.path.dirname(dst) |
124 | + new_name = os.path.basename(dst) |
125 | + |
126 | + total_files = sum(len(files) for path in srcPaths for r, d, files in os.walk(path) if os.path.isdir(path)) + sum(1 for path in srcPaths if os.path.isfile(path)) |
127 | + total_size = getTotalSize(srcPaths) |
128 | + |
129 | + current_file = 1 |
130 | + |
131 | + if total_files > 1: |
132 | + console.print(f"\n[#ea2a6f]{process}:[/#ea2a6f] [bold cyan]{total_files} files[/bold cyan]\n") |
133 | + else: |
134 | + for src_path in srcPaths: |
135 | + if os.path.isfile(src_path): |
136 | + console.print(f"\n[#ea2a6f]{process}:[/#ea2a6f] [bold cyan] {os.path.basename(src_path)} [/bold cyan]\n") |
137 | + |
138 | + if verbose: |
139 | + for src_path in srcPaths: |
140 | + if os.path.isfile(src_path): |
141 | + dst_path = os.path.join(dst_dir, os.path.basename(src_path) if not new_name else new_name) |
142 | + terminate = verbose_copy(src_path, dst_path, console, current_file, total_files, file_name=os.path.basename(src_path)) |
143 | + current_file += 1 |
144 | + if terminate == 'c': |
145 | + console.print("\n[bold red]\[-][/bold red][bold white] Operation cancelled by user.[/bold white]\n") |
146 | + sys.exit(1) |
147 | + else: |
148 | + for root, dirs, files in os.walk(src_path): |
149 | + for file in files: |
150 | + src_file_path = os.path.join(root, file) |
151 | + relative_path = os.path.relpath(src_file_path, start=src_path) |
152 | + dst_file_path = os.path.join(dst_dir, os.path.basename(src_path) if not new_name else new_name, relative_path) |
153 | + os.makedirs(os.path.dirname(src_file_path), exist_ok=True) |
154 | + terminate = verbose_copy(src_file_path, dst_file_path, console, current_file, total_files, file_name=file) |
155 | + current_file += 1 |
156 | + if terminate == 'c': |
157 | + console.print("\n[bold red]\[-][/bold red][bold white] Operation cancelled by user.[/bold white]\n") |
158 | + sys.exit(1) |
159 | + else: |
160 | + with Progress( |
161 | + BarColumn(bar_width=50), |
162 | + "[progress.percentage]{task.percentage:>3.0f}%", |
163 | + TimeRemainingColumn(), |
164 | + "[#ea2a6f][[/#ea2a6f]", |
165 | + FileSizeColumn(), |
166 | + "[#ea2a6f]/[/#ea2a6f]", |
167 | + TextColumn("[bold cyan]{task.fields[total_size]}[/bold cyan]"), |
168 | + "[#ea2a6f]][/#ea2a6f]", |
169 | + console=console, |
170 | + auto_refresh=False |
171 | + ) as progress: |
172 | + task = progress.add_task("", total=total_size, total_size=format_file_size(total_size)) |
173 | + |
174 | + for src_path in srcPaths: |
175 | + if os.path.isfile(src_path): |
176 | + dst_file_path = os.path.join(dst_dir, os.path.basename(src_path) if not new_name else new_name) |
177 | + terminate = regular_copy(src_path, dst_file_path, console, task, progress, file_name=os.path.basename(src_path)) |
178 | + if terminate == 'c': |
179 | + console.print("\n[bold red]\[-][/bold red][bold white] Operation cancelled by user.[/bold white]\n") |
180 | + sys.exit(1) |
181 | + else: |
182 | + for root, dirs, files in os.walk(src_path): |
183 | + for file in files: |
184 | + src_file_path = os.path.join(root, file) |
185 | + relative_path = os.path.relpath(src_file_path, start=src_path) |
186 | + dst_file_path = os.path.join(dst_dir, os.path.basename(src_path) if not new_name else new_name, relative_path) |
187 | + os.makedirs(os.path.dirname(dst_file_path), exist_ok=True) |
188 | + terminate = regular_copy(src_file_path, dst_file_path, console, task, progress, file_name=file) |
189 | + if terminate == 'c': |
190 | + console.print("\n[bold red]\[-][/bold red][bold white] Operation cancelled by user.[/bold white]\n") |
191 | + sys.exit(1) |
192 | + |
193 | + return srcPaths |
194 | + |
195 | + |
196 | +def download(): |
197 | + console = Console() |
198 | + urls = sys.argv[1:] |
199 | + |
200 | + if len(urls) == 0: |
201 | + console.print("\n[bold red][-][/bold red] No URL provided.\n") |
202 | + sys.exit() |
203 | + |
204 | + num_urls = len(urls) |
205 | + for url in urls: |
206 | + if url.startswith('-'): |
207 | + num_urls -= 1 |
208 | + elif not validators.url(url): |
209 | + console.print(f"\n[bold red][-][/bold red] Invalid URL: [bold yellow]{url}[/bold yellow]\n") |
210 | + sys.exit() |
211 | + |
212 | + console.print(f"\n[#ea2a6f]Downloading:[/#ea2a6f] [bold yellow]{num_urls}[/bold yellow] [bold cyan]files[/bold cyan]\n") |
213 | + |
214 | + errors = [] |
215 | + for url in urls: |
216 | + try: |
217 | + if url.startswith('-'): |
218 | + continue |
219 | + |
220 | + response = requests.get(url, stream=True, allow_redirects=True) |
221 | + total_size_in_bytes = int(response.headers.get('content-length', 0)) |
222 | + content_disposition = response.headers.get('content-disposition') |
223 | + if content_disposition: |
224 | + destination_path = re.findall('filename="(.+)"', content_disposition)[0] |
225 | + else: |
226 | + destination_path = os.path.basename(url) |
227 | + |
228 | + with Progress( |
229 | + BarColumn(bar_width=50), |
230 | + "[progress.percentage]{task.percentage:>3.0f}%", |
231 | + TimeRemainingColumn(), |
232 | + "[#ea2a6f][[/#ea2a6f]", |
233 | + CustomFileSizeColumn(), |
234 | + "[#ea2a6f]][/#ea2a6f]", |
235 | + f" {destination_path}", # This line will print the filename at the end |
236 | + console=console, |
237 | + auto_refresh=True |
238 | + ) as progress: |
239 | + task_id = progress.add_task("Downloading", total=total_size_in_bytes) |
240 | + block_size = 1024 # 1 Kibibyte |
241 | + with open(destination_path, 'wb') as file: |
242 | + for data in response.iter_content(block_size): |
243 | + file.write(data) |
244 | + progress.update(task_id, advance=block_size) |
245 | + except KeyboardInterrupt: |
246 | + console.print("\n[bold red]\[-][/bold red][bold white] Operation cancelled by user.[/bold white]\n") |
247 | + sys.exit(1) |
248 | + |
249 | + except Exception as e: |
250 | + console.print(f"\n[bold red]\[-][/bold red][bold white] Could not download file: [bold yellow]{url}[/bold yellow]\n") |
251 | + print(e) |
252 | + errors.append(url) |
253 | + |
254 | + if len(errors) == 0: |
255 | + console.print("\n[bold green]Download completed![/bold green]\n") |
256 | + else: |
257 | + console.print("[bold red]The following files could not be downloaded:[/bold red]\n") |
258 | + for error in errors: |
259 | + console.print(f"[bold red] -[/bold red][bold yellow]{error}[/bold yellow]\n") |
260 | + |
261 | + |
262 | +def copy(): |
263 | + run('Copying') |
264 | + |
265 | + |
266 | +def move(): |
267 | + src_paths = run('Moving') |
268 | + for src_path in src_paths: |
269 | + if os.path.isfile(src_path): |
270 | + os.remove(src_path) |
271 | + else: |
272 | + shutil.rmtree(src_path) |
273 | + |
274 | + |
275 | +def main(): |
276 | + if argMove: |
277 | + move() |
278 | + elif argCopy: |
279 | + copy() |
280 | + elif argDownload: |
281 | + download() |
282 | + else: |
283 | + hlp() |
284 | + |
285 | + |
286 | +if __name__ == "__main__": |
287 | + main() |
288 | diff --git a/build/lib/ptrack/methods.py b/build/lib/ptrack/methods.py |
289 | new file mode 100644 |
290 | index 0000000..d79173d |
291 | --- /dev/null |
292 | +++ b/build/lib/ptrack/methods.py |
293 | @@ -0,0 +1,136 @@ |
294 | +import os |
295 | +import sys |
296 | +import requests |
297 | +from rich.console import Console |
298 | +from rich.progress import Progress, TextColumn, BarColumn, TimeRemainingColumn, FileSizeColumn, Task, DownloadColumn, TimeElapsedColumn |
299 | +from rich.text import Text |
300 | +from datetime import timedelta |
301 | +from humanize import naturalsize |
302 | + |
303 | +console = Console() |
304 | + |
305 | + |
306 | +def getTotalSize(srcPaths): |
307 | + total_size = 0 |
308 | + for path in srcPaths: |
309 | + if os.path.isfile(path): |
310 | + total_size += os.path.getsize(path) |
311 | + else: |
312 | + for r, d, files in os.walk(path): |
313 | + for f in files: |
314 | + fp = os.path.join(r, f) |
315 | + total_size += os.path.getsize(fp) |
316 | + return total_size |
317 | + |
318 | + |
319 | +def format_file_size(file_size): |
320 | + if file_size >= 1000 ** 4: # Terabyte |
321 | + return f"{round(file_size / (1000 ** 4))} TB" |
322 | + elif file_size >= 1000 ** 3: # Gigabyte |
323 | + return f"{round(file_size / (1000 ** 3))} GB" |
324 | + elif file_size >= 1000 ** 2: # Megabyte |
325 | + return f"{round(file_size / (1000 ** 2))} MB" |
326 | + elif file_size >= 1000: # Kilobyte |
327 | + return f"{round(file_size / 1000)} kB" |
328 | + else: # Byte |
329 | + return f"{file_size} bytes" |
330 | + |
331 | + |
332 | +def regular_copy(src, dst, console, task, progress, file_name): |
333 | + operation_cancelled = False |
334 | + try: |
335 | + with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst: |
336 | + while True: |
337 | + buf = fsrc.read(1024*1024) |
338 | + if not buf or operation_cancelled: |
339 | + break |
340 | + fdst.write(buf) |
341 | + progress.update(task, advance=len(buf)) |
342 | + progress.refresh() |
343 | + |
344 | + except KeyboardInterrupt: |
345 | + operation_cancelled = True |
346 | + progress.stop() |
347 | + return "c" |
348 | + |
349 | + |
350 | +def verbose_copy(src, dst, console, current, total_files, file_name): |
351 | + operation_cancelled = False |
352 | + file_size = os.path.getsize(src) |
353 | + |
354 | + with Progress( |
355 | + BarColumn(bar_width=50), |
356 | + "[progress.percentage]{task.percentage:>3.0f}%", |
357 | + TimeRemainingColumn(), |
358 | + "[#ea2a6f][[/#ea2a6f]", |
359 | + FileSizeColumn(), |
360 | + "[#ea2a6f]/[/#ea2a6f]", |
361 | + TextColumn(f"[bold cyan]{format_file_size(file_size)}[/bold cyan]"), |
362 | + "[#ea2a6f]][/#ea2a6f]", |
363 | + f"({current} of {total_files}) - {file_name}", |
364 | + console=console, |
365 | + auto_refresh=False |
366 | + ) as progress: |
367 | + task = progress.add_task("", total=file_size, file_size=format_file_size(file_size)) |
368 | + |
369 | + try: |
370 | + with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst: |
371 | + while not progress.finished: |
372 | + buf = fsrc.read(1024*1024) |
373 | + if not buf or operation_cancelled: |
374 | + break |
375 | + fdst.write(buf) |
376 | + progress.update(task, advance=len(buf)) |
377 | + progress.refresh() |
378 | + except KeyboardInterrupt: |
379 | + operation_cancelled = True |
380 | + progress.stop() |
381 | + return "c" |
382 | + |
383 | + |
384 | +def hlp(): |
385 | + print(""" |
386 | +usage: ptrack [-h] [-v] [-c] [-m] [-d] [-V] |
387 | + |
388 | +A simple CLI utility for asthetically tracking progress when copying or moving files. |
389 | + |
390 | +options: |
391 | + -h, --help show this help message and exit |
392 | + -v, --verbose verbose output |
393 | + -c, --copy copy files (You can use `ptc` instead of `ptrack -c`) |
394 | + -m, --move move files (You can use `ptm` instead of `ptrack -m`) |
395 | + -d, --download download files (You can use `ptd` instead of `ptrack -d`) |
396 | + -V, --version show program's version number and exit |
397 | +""") |
398 | + |
399 | + |
400 | +class CustomFileSizeColumn(FileSizeColumn, TimeElapsedColumn): |
401 | + def render(self, task): |
402 | + completed = task.completed |
403 | + total = task.total |
404 | + elapsed = task.elapsed |
405 | + |
406 | + if elapsed > 0.0: # Prevent division by zero |
407 | + download_speed = completed / elapsed # calculate download rate |
408 | + else: |
409 | + download_speed = 0 |
410 | + |
411 | + if total: |
412 | + size = Text.assemble( |
413 | + (f"{self._human_readable_size(completed)}", "green"), # completed |
414 | + (" / ", "none"), # separator |
415 | + (f"{self._human_readable_size(total)}", "red"), # total |
416 | + (" [", "none"), # opening square bracket |
417 | + (f"{self._human_readable_size(download_speed)}/s", "blue"), # download rate |
418 | + ("]", "none"), # closing square bracket |
419 | + ) |
420 | + else: |
421 | + size = Text(str(self._human_readable_size(completed))) |
422 | + return size |
423 | + |
424 | + def _human_readable_size(self, size: int) -> str: |
425 | + for unit in ['B', 'KB', 'MB', 'GB', 'TB']: |
426 | + if abs(size) < 1024.0: |
427 | + return f"{size:.1f}{unit}" |
428 | + size /= 1024.0 |
429 | + return f"{size:.1f}PB" |
430 | diff --git a/dist/ptrack-0.2.2-py3-none-any.whl b/dist/ptrack-0.2.2-py3-none-any.whl |
431 | new file mode 100644 |
432 | index 0000000..b1836bd |
433 | Binary files /dev/null and b/dist/ptrack-0.2.2-py3-none-any.whl differ |
434 | diff --git a/dist/ptrack-0.2.2.tar.gz b/dist/ptrack-0.2.2.tar.gz |
435 | new file mode 100644 |
436 | index 0000000..ac589df |
437 | Binary files /dev/null and b/dist/ptrack-0.2.2.tar.gz differ |
438 | diff --git a/ptrack.egg-info/PKG-INFO b/ptrack.egg-info/PKG-INFO |
439 | new file mode 100644 |
440 | index 0000000..2ce3426 |
441 | --- /dev/null |
442 | +++ b/ptrack.egg-info/PKG-INFO |
443 | @@ -0,0 +1,7 @@ |
444 | +Metadata-Version: 2.1 |
445 | +Name: ptrack |
446 | +Version: 0.2.2 |
447 | +Summary: A simple CLI utility for asthetically tracking progress when copying, moving or downloading files. |
448 | +Author: Connor Etherington |
449 | +Author-email: [email protected] |
450 | +License-File: LICENSE |
451 | diff --git a/ptrack.egg-info/SOURCES.txt b/ptrack.egg-info/SOURCES.txt |
452 | new file mode 100644 |
453 | index 0000000..086a784 |
454 | --- /dev/null |
455 | +++ b/ptrack.egg-info/SOURCES.txt |
456 | @@ -0,0 +1,12 @@ |
457 | +LICENSE |
458 | +README.md |
459 | +setup.py |
460 | +ptrack/__init__.py |
461 | +ptrack/main.py |
462 | +ptrack/methods.py |
463 | +ptrack.egg-info/PKG-INFO |
464 | +ptrack.egg-info/SOURCES.txt |
465 | +ptrack.egg-info/dependency_links.txt |
466 | +ptrack.egg-info/entry_points.txt |
467 | +ptrack.egg-info/requires.txt |
468 | +ptrack.egg-info/top_level.txt |
469 | diff --git a/ptrack.egg-info/dependency_links.txt b/ptrack.egg-info/dependency_links.txt |
470 | new file mode 100644 |
471 | index 0000000..8b13789 |
472 | --- /dev/null |
473 | +++ b/ptrack.egg-info/dependency_links.txt |
474 | @@ -0,0 +1 @@ |
475 | + |
476 | diff --git a/ptrack.egg-info/entry_points.txt b/ptrack.egg-info/entry_points.txt |
477 | new file mode 100644 |
478 | index 0000000..ea851b3 |
479 | --- /dev/null |
480 | +++ b/ptrack.egg-info/entry_points.txt |
481 | @@ -0,0 +1,5 @@ |
482 | +[console_scripts] |
483 | +ptc = ptrack.main:copy |
484 | +ptd = ptrack.main:download |
485 | +ptm = ptrack.main:move |
486 | +ptrack = ptrack.main:main |
487 | diff --git a/ptrack.egg-info/requires.txt b/ptrack.egg-info/requires.txt |
488 | new file mode 100644 |
489 | index 0000000..d19a378 |
490 | --- /dev/null |
491 | +++ b/ptrack.egg-info/requires.txt |
492 | @@ -0,0 +1,6 @@ |
493 | +rich |
494 | +argparse |
495 | +requests |
496 | +validators |
497 | +setuptools |
498 | +humanize |
499 | diff --git a/ptrack.egg-info/top_level.txt b/ptrack.egg-info/top_level.txt |
500 | new file mode 100644 |
501 | index 0000000..c003217 |
502 | --- /dev/null |
503 | +++ b/ptrack.egg-info/top_level.txt |
504 | @@ -0,0 +1 @@ |
505 | +ptrack |
506 | diff --git a/ptrack/__init__.py b/ptrack/__init__.py |
507 | index 9b03a65..112f15e 100644 |
508 | --- a/ptrack/__init__.py |
509 | +++ b/ptrack/__init__.py |
510 | @@ -1,6 +1,5 @@ |
511 | import argparse |
512 | -import argcomplete |
513 | -version="0.2.1" |
514 | +version="0.2.2" |
515 | |
516 | parser = argparse.ArgumentParser(description='A simple CLI utility for asthetically tracking progress when copying or moving files.') |
517 | parser.add_argument('-v', '--verbose', action='store_true', help='verbose output') |
518 | @@ -9,7 +8,6 @@ parser.add_argument('-m', '--move', action='store_true', help='move files (You c |
519 | parser.add_argument('-d', '--download', action='store_true', help='download files (You can use `ptd` instead of `ptrack -d`)') |
520 | parser.add_argument('-V', '--version', action='version', version='%(prog)s' + version) |
521 | |
522 | -argcomplete.autocomplete(parser) |
523 | args, unknown = parser.parse_known_args() |
524 | |
525 | verbose = args.verbose |
526 | diff --git a/ptrack/main.py b/ptrack/main.py |
527 | index 5730123..48523fa 100644 |
528 | --- a/ptrack/main.py |
529 | +++ b/ptrack/main.py |
530 | @@ -1,4 +1,5 @@ |
531 | import os |
532 | +import re |
533 | import sys |
534 | import ptrack |
535 | from ptrack.methods import format_file_size, regular_copy, verbose_copy, hlp, getTotalSize, CustomFileSizeColumn |
536 | @@ -58,7 +59,7 @@ def run(process): |
537 | for src_path in srcPaths: |
538 | if os.path.isfile(src_path): |
539 | dst_path = os.path.join(dst_dir, os.path.basename(src_path) if not new_name else new_name) |
540 | - terminate = verbose_copy(src_path, dst_path, console, current_file, total_files) |
541 | + terminate = verbose_copy(src_path, dst_path, console, current_file, total_files, file_name=os.path.basename(src_path)) |
542 | current_file += 1 |
543 | if terminate == 'c': |
544 | console.print("\n[bold red]\[-][/bold red][bold white] Operation cancelled by user.[/bold white]\n") |
545 | @@ -69,8 +70,8 @@ def run(process): |
546 | src_file_path = os.path.join(root, file) |
547 | relative_path = os.path.relpath(src_file_path, start=src_path) |
548 | dst_file_path = os.path.join(dst_dir, os.path.basename(src_path) if not new_name else new_name, relative_path) |
549 | - os.makedirs(os.path.dirname(dst_file_path), exist_ok=True) |
550 | - terminate = verbose_copy(src_file_path, dst_file_path, console, current_file, total_files) |
551 | + os.makedirs(os.path.dirname(src_file_path), exist_ok=True) |
552 | + terminate = verbose_copy(src_file_path, dst_file_path, console, current_file, total_files, file_name=file) |
553 | current_file += 1 |
554 | if terminate == 'c': |
555 | console.print("\n[bold red]\[-][/bold red][bold white] Operation cancelled by user.[/bold white]\n") |
556 | @@ -93,7 +94,7 @@ def run(process): |
557 | for src_path in srcPaths: |
558 | if os.path.isfile(src_path): |
559 | dst_file_path = os.path.join(dst_dir, os.path.basename(src_path) if not new_name else new_name) |
560 | - terminate = regular_copy(src_path, dst_file_path, console, task, progress) |
561 | + terminate = regular_copy(src_path, dst_file_path, console, task, progress, file_name=os.path.basename(src_path)) |
562 | if terminate == 'c': |
563 | console.print("\n[bold red]\[-][/bold red][bold white] Operation cancelled by user.[/bold white]\n") |
564 | sys.exit(1) |
565 | @@ -104,7 +105,7 @@ def run(process): |
566 | relative_path = os.path.relpath(src_file_path, start=src_path) |
567 | dst_file_path = os.path.join(dst_dir, os.path.basename(src_path) if not new_name else new_name, relative_path) |
568 | os.makedirs(os.path.dirname(dst_file_path), exist_ok=True) |
569 | - terminate = regular_copy(src_file_path, dst_file_path, console, task, progress) |
570 | + terminate = regular_copy(src_file_path, dst_file_path, console, task, progress, file_name=file) |
571 | if terminate == 'c': |
572 | console.print("\n[bold red]\[-][/bold red][bold white] Operation cancelled by user.[/bold white]\n") |
573 | sys.exit(1) |
574 | @@ -113,7 +114,6 @@ def run(process): |
575 | |
576 | |
577 | def download(): |
578 | - |
579 | console = Console() |
580 | urls = sys.argv[1:] |
581 | |
582 | @@ -137,9 +137,13 @@ def download(): |
583 | if url.startswith('-'): |
584 | continue |
585 | |
586 | - response = requests.get(url, stream=True) |
587 | + response = requests.get(url, stream=True, allow_redirects=True) |
588 | total_size_in_bytes = int(response.headers.get('content-length', 0)) |
589 | - destination_path = os.path.basename(url) |
590 | + content_disposition = response.headers.get('content-disposition') |
591 | + if content_disposition: |
592 | + destination_path = re.findall('filename="(.+)"', content_disposition)[0] |
593 | + else: |
594 | + destination_path = os.path.basename(url) |
595 | |
596 | with Progress( |
597 | BarColumn(bar_width=50), |
598 | @@ -148,6 +152,7 @@ def download(): |
599 | "[#ea2a6f][[/#ea2a6f]", |
600 | CustomFileSizeColumn(), |
601 | "[#ea2a6f]][/#ea2a6f]", |
602 | + f" {destination_path}", # This line will print the filename at the end |
603 | console=console, |
604 | auto_refresh=True |
605 | ) as progress: |
606 | diff --git a/ptrack/methods.py b/ptrack/methods.py |
607 | index 1c7482c..d79173d 100644 |
608 | --- a/ptrack/methods.py |
609 | +++ b/ptrack/methods.py |
610 | @@ -5,7 +5,7 @@ from rich.console import Console |
611 | from rich.progress import Progress, TextColumn, BarColumn, TimeRemainingColumn, FileSizeColumn, Task, DownloadColumn, TimeElapsedColumn |
612 | from rich.text import Text |
613 | from datetime import timedelta |
614 | -from humanize import naturalsize # Make sure to install this package using pip |
615 | +from humanize import naturalsize |
616 | |
617 | console = Console() |
618 | |
619 | @@ -36,7 +36,7 @@ def format_file_size(file_size): |
620 | return f"{file_size} bytes" |
621 | |
622 | |
623 | -def regular_copy(src, dst, console, task, progress): |
624 | +def regular_copy(src, dst, console, task, progress, file_name): |
625 | operation_cancelled = False |
626 | try: |
627 | with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst: |
628 | @@ -54,7 +54,7 @@ def regular_copy(src, dst, console, task, progress): |
629 | return "c" |
630 | |
631 | |
632 | -def verbose_copy(src, dst, console, current, total_files): |
633 | +def verbose_copy(src, dst, console, current, total_files, file_name): |
634 | operation_cancelled = False |
635 | file_size = os.path.getsize(src) |
636 | |
637 | @@ -67,7 +67,7 @@ def verbose_copy(src, dst, console, current, total_files): |
638 | "[#ea2a6f]/[/#ea2a6f]", |
639 | TextColumn(f"[bold cyan]{format_file_size(file_size)}[/bold cyan]"), |
640 | "[#ea2a6f]][/#ea2a6f]", |
641 | - f"({current} of {total_files})", |
642 | + f"({current} of {total_files}) - {file_name}", |
643 | console=console, |
644 | auto_refresh=False |
645 | ) as progress: |
646 | diff --git a/recipe/meta.yaml b/recipe/meta.yaml |
647 | index 571dcf1..3747a0a 100644 |
648 | --- a/recipe/meta.yaml |
649 | +++ b/recipe/meta.yaml |
650 | @@ -1,6 +1,6 @@ |
651 | package: |
652 | name: ptrack |
653 | - version: 0.2.1 |
654 | + version: 0.2.2 |
655 | |
656 | source: |
657 | path: .. |
658 | diff --git a/setup.py b/setup.py |
659 | index a769eb4..4728915 100644 |
660 | --- a/setup.py |
661 | +++ b/setup.py |
662 | @@ -2,7 +2,7 @@ from setuptools import setup, find_packages |
663 | |
664 | setup( |
665 | name='ptrack', |
666 | - version="0.2.1", |
667 | + version="0.2.2", |
668 | description='A simple CLI utility for asthetically tracking progress when copying, moving or downloading files.', |
669 | author='Connor Etherington', |
670 | author_email='[email protected]', |
671 | @@ -12,6 +12,8 @@ setup( |
672 | 'argparse', |
673 | 'requests', |
674 | 'validators', |
675 | + 'setuptools', |
676 | + 'humanize', |
677 | ], |
678 | entry_points={ |
679 | 'console_scripts': [ |