textfmt 0.1.1__py3-none-any.whl → 0.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: textfmt
3
- Version: 0.1.1
4
- Summary: A Python module for ANSI text formatting, word art, and table styling
3
+ Version: 0.2.1
4
+ Summary: Terminal Formatting for Humans
5
5
  Author-email: Rihaan Meher <meherrihaan@gmail.com>
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/sharktide/textformat
@@ -55,6 +55,28 @@ data = [
55
55
  print(TableFormatter.generate(headers, data))
56
56
  ```
57
57
 
58
+ File Download Progress Bars
59
+
60
+ ```python
61
+ from textformat.progress import Color, DownloadProgressBar
62
+ from pathlib import Path
63
+ def download_with_progress(url: str, output_path: Path, download_color, complete_color):
64
+ response = requests.get(url, stream=True)
65
+ total = int(response.headers.get('content-length', 0))
66
+
67
+ if response.status_code != 200:
68
+ raise Exception(f"Failed to download from {url}. HTTP status: {response.status_code}")
69
+
70
+ progress = DownloadProgressBar(total, prefix=output_path.name,
71
+ download_color=download_color, complete_color=complete_color)
72
+ with open(output_path, "wb") as f:
73
+ for chunk in response.iter_content(chunk_size=8192):
74
+ if chunk:
75
+ f.write(chunk)
76
+ progress.update(progress.downloaded + len(chunk))
77
+ print()
78
+ download_with_progress('https://huggingface.co/sharktide/recyclebot0/resolve/main/tf_model.h5', Path("tf_model.h5"), Colors.CYAN, Colors.GREEN)
79
+ ```
58
80
  ## License
59
81
 
60
82
  MIT License – Free to use and modify.
@@ -0,0 +1,10 @@
1
+ textfmt-0.2.1.dist-info/licenses/LICENSE,sha256=Msmy46KiAR2wmzeCe3kSl-wEt7ptbTZOAzdwUUyFq_M,1090
2
+ textformat/__init__.py,sha256=Yz9706rsciMHmMHDvzqS1LxQm04N9NM5rO-xUaFLm8c,306
3
+ textformat/progress.py,sha256=2EXWQxEVjnd9eHmEJUGmH6e3TVqXC5ZNcS-ez6L-W-A,3444
4
+ textformat/table.py,sha256=W51T9__0Qtgv_nxn6s2bit4tduhgiXZ3FwjODGvLf3I,746
5
+ textformat/textformat.py,sha256=hYGgLkra7HIdG5mtVcDvAHOMzbv-0q9TFs82jjdOdew,1681
6
+ textformat/word_art.py,sha256=GsJka0ukV23FTvhuyuGRChhNGOjTWOdKBK3h0e-LnX8,318
7
+ textfmt-0.2.1.dist-info/METADATA,sha256=BserKxfvwaxtgi0GjyNnAseG1XfHSys2VtH9tdd9sMA,2539
8
+ textfmt-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
+ textfmt-0.2.1.dist-info/top_level.txt,sha256=Nf6G1sI6EqA2opfIdIio6ZqKNbpT2EtYf5cd0sKgPRo,11
10
+ textfmt-0.2.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.8.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
textformat/__init__.py CHANGED
@@ -1,5 +1,9 @@
1
1
  # textfmt/__init__.py
2
- from .textformat import TextFormat, bcolors
2
+ from .textformat import TextFormat, bcolors, enable_windows_ansi_support
3
3
  from .word_art import WordArt
4
4
  from .table import TableFormatter
5
- __all__ = ["TextFormat", "bcolors", "WordArt", "TableFormatter"]
5
+ import os
6
+
7
+ enable_windows_ansi_support()
8
+
9
+ __all__ = ["TextFormat", "bcolors", "WordArt", "TableFormatter", "enable_windows_ansi_support"]
textformat/progress.py ADDED
@@ -0,0 +1,98 @@
1
+ import requests
2
+ import time
3
+ from pathlib import Path
4
+ import sys
5
+
6
+ # Define color codes for terminal (ANSI escape codes)
7
+ class Colors:
8
+ RESET = "\033[0m"
9
+ GREEN = "\033[92m"
10
+ BLUE = "\033[94m"
11
+ RED = "\033[91m"
12
+ YELLOW = "\033[93m"
13
+ MAGENTA = "\033[95m"
14
+ CYAN = "\033[96m"
15
+ WHITE = "\033[97m"
16
+ LIGHT_GREEN = "\033[92m"
17
+ LIGHT_BLUE = "\033[94m"
18
+ LIGHT_RED = "\033[91m"
19
+ LIGHT_YELLOW = "\033[93m"
20
+ LIGHT_MAGENTA = "\033[95m"
21
+ LIGHT_CYAN = "\033[96m"
22
+
23
+ ALL_COLORS = [
24
+ GREEN, BLUE, RED, YELLOW, MAGENTA, CYAN, WHITE,
25
+ LIGHT_GREEN, LIGHT_BLUE, LIGHT_RED, LIGHT_YELLOW, LIGHT_MAGENTA, LIGHT_CYAN
26
+ ]
27
+
28
+ class DownloadProgressBar:
29
+ def __init__(self, total, prefix='', length=40, fill='━', empty=' ', print_end="\r",
30
+ download_color=Colors.GREEN, complete_color=Colors.BLUE):
31
+ self.total = total
32
+ self.prefix = prefix
33
+ self.length = length
34
+ self.fill = fill
35
+ self.empty = empty
36
+ self.print_end = print_end
37
+ self.download_color = download_color
38
+ self.complete_color = complete_color
39
+ self.start_time = time.time()
40
+ self.downloaded = 0
41
+
42
+ def update(self, downloaded):
43
+ now = time.time()
44
+ self.downloaded = downloaded
45
+
46
+ if self.total > 0:
47
+ percent = 100 * (self.downloaded / float(self.total))
48
+ filled_length = int(self.length * self.downloaded // self.total)
49
+ total_size = self.format_size(self.total)
50
+ else:
51
+ percent = 100
52
+ filled_length = 40
53
+ total_size = "?"
54
+
55
+ bar = self.fill * filled_length + self.empty * (self.length - filled_length)
56
+ current_size = self.format_size(self.downloaded)
57
+
58
+ # Speed (bytes per second)
59
+ elapsed = now - self.start_time
60
+ speed_bps = self.downloaded / elapsed if elapsed > 0 else 0
61
+ speed_str = self.format_size(speed_bps) + "/s" if speed_bps > 0 else "?"
62
+
63
+ # ETA
64
+ remaining = self.total - self.downloaded if self.total > 0 else 0
65
+ eta_seconds = remaining / speed_bps if self.total > 0 and speed_bps > 0 else 0
66
+ eta_str = self.format_time(eta_seconds) if self.total > 0 else "?"
67
+
68
+ # Choose color
69
+ color = self.complete_color if self.downloaded == self.total and self.total > 0 else self.download_color
70
+
71
+ # Print
72
+ sys.stdout.write(
73
+ f'\r{self.prefix} {color}{bar}{Colors.RESET} {percent:5.1f}% • '
74
+ f'{current_size}/{total_size} • {speed_str} • {eta_str}'
75
+ )
76
+ sys.stdout.flush()
77
+
78
+ if self.downloaded == self.total and self.total > 0:
79
+ sys.stdout.write(self.print_end)
80
+ sys.stdout.flush()
81
+
82
+ @staticmethod
83
+ def format_size(size_in_bytes):
84
+ """Format the size in a human-readable format."""
85
+ for unit in ['B', 'KiB', 'MiB', 'GiB', 'TiB']:
86
+ if size_in_bytes < 1024:
87
+ return f"{size_in_bytes:.1f} {unit}"
88
+ size_in_bytes /= 1024
89
+ return f"{size_in_bytes:.1f} PiB"
90
+
91
+ @staticmethod
92
+ def format_time(seconds):
93
+ """Format seconds into H:MM:SS or M:SS."""
94
+ if seconds < 0.1:
95
+ return "0:00"
96
+ m, s = divmod(int(seconds + 0.5), 60)
97
+ h, m = divmod(m, 60)
98
+ return f"{h}:{m:02}:{s:02}" if h else f"{m}:{s:02}"
textformat/table.py CHANGED
@@ -4,10 +4,15 @@ class TableFormatter:
4
4
  @staticmethod
5
5
  def generate(headers, data):
6
6
  """ Creates a formatted table for structured output """
7
+ # Calculate max width per column
7
8
  col_widths = [max(len(str(item)) for item in col) for col in zip(headers, *data)]
8
- border = "+".join("-" * (w + 2) for w in col_widths)
9
+
10
+ def build_border():
11
+ return "+" + "+".join("-" * (w + 2) for w in col_widths) + "+"
9
12
 
10
13
  def format_row(row):
11
14
  return "| " + " | ".join(f"{str(item).ljust(w)}" for item, w in zip(row, col_widths)) + " |"
12
15
 
13
- return f"{border}\n{format_row(headers)}\n{border}\n" + "\n".join(format_row(row) for row in data) + f"\n{border}"
16
+ border = build_border()
17
+ rows = [format_row(headers), border] + [format_row(row) for row in data]
18
+ return f"{border}\n" + "\n".join(rows) + f"\n{border}"
textformat/textformat.py CHANGED
@@ -1,3 +1,21 @@
1
+ import os
2
+
3
+ def enable_windows_ansi_support() -> None:
4
+ """
5
+ Enables ANSI escape sequence support in Windows terminals (safe version).
6
+ """
7
+ if os.name == 'nt':
8
+ try:
9
+ import ctypes
10
+ kernel32 = ctypes.windll.kernel32
11
+ handle = kernel32.GetStdHandle(-11)
12
+ mode = ctypes.c_ulong()
13
+ if kernel32.GetConsoleMode(handle, ctypes.byref(mode)):
14
+ mode.value |= 0x0004
15
+ kernel32.SetConsoleMode(handle, mode)
16
+ except Exception:
17
+ pass
18
+
1
19
  class bcolors:
2
20
  HEADER = '\033[95m'
3
21
  OKBLUE = '\033[94m'
@@ -9,7 +27,6 @@ class bcolors:
9
27
  ENDC = '\033[0m'
10
28
  BOLD = '\033[1m'
11
29
  UNDERLINE = '\033[4m'
12
-
13
30
  class TextFormat:
14
31
  """ ANSI Escape Code Formatting for Python CLI Output """
15
32
  RESET = "\x1b[0m"
@@ -1,9 +0,0 @@
1
- textfmt-0.1.1.dist-info/licenses/LICENSE,sha256=Msmy46KiAR2wmzeCe3kSl-wEt7ptbTZOAzdwUUyFq_M,1090
2
- textformat/__init__.py,sha256=fyib7AnpkuEZ_PAzx6AO5SVKNTB5kyqk5NnJBXx7TYw,200
3
- textformat/table.py,sha256=GA7MsMWNuug61XxK9Ot3SOg5bl9zh5GO9Hae8-Y2qeE,604
4
- textformat/textformat.py,sha256=yz6KstoDtrIgoA_b4ZFJAY9EfcylSjeeJ_euhPf8cpw,1121
5
- textformat/word_art.py,sha256=GsJka0ukV23FTvhuyuGRChhNGOjTWOdKBK3h0e-LnX8,318
6
- textfmt-0.1.1.dist-info/METADATA,sha256=HC4hKXmxtK8eHMssLwSxVQHgrrXg6ouOhIJpcs7iKAg,1566
7
- textfmt-0.1.1.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
8
- textfmt-0.1.1.dist-info/top_level.txt,sha256=Nf6G1sI6EqA2opfIdIio6ZqKNbpT2EtYf5cd0sKgPRo,11
9
- textfmt-0.1.1.dist-info/RECORD,,