replbase 0.0.24__tar.gz → 0.0.26__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: replbase
3
- Version: 0.0.24
3
+ Version: 0.0.26
4
4
  Summary: "Combination of other REPL tools into a reusable class that generates a REPL"
5
5
  License: MIT
6
6
  Author: Joseph Bochinski
@@ -12,6 +12,7 @@ Classifier: Programming Language :: Python :: 3.12
12
12
  Requires-Dist: prompt-toolkit (>=3.0.48,<4.0.0)
13
13
  Requires-Dist: ptpython (>=3.0.29,<4.0.0)
14
14
  Requires-Dist: rich (>=13.9.4,<14.0.0)
15
+ Requires-Dist: tabulate (>=0.9.0,<0.10.0)
15
16
  Description-Content-Type: text/markdown
16
17
 
17
18
  # replbase
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "replbase"
7
- version = "0.0.24"
7
+ version = "0.0.26"
8
8
  description = "\"Combination of other REPL tools into a reusable class that generates a REPL\""
9
9
  authors = [ "Joseph Bochinski <stirgejr@gmail.com>",]
10
10
  license = "MIT"
@@ -15,3 +15,4 @@ python = "^3.12"
15
15
  prompt-toolkit = "^3.0.48"
16
16
  ptpython = "^3.0.29"
17
17
  rich = "^13.9.4"
18
+ tabulate = "^0.9.0"
@@ -15,9 +15,14 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  import argparse
18
+ import grp
19
+ import math
18
20
  import os
21
+ import pwd
19
22
  import re
20
23
  import shlex
24
+ import stat
25
+ import time
21
26
 
22
27
  from dataclasses import dataclass, field
23
28
  from typing import Any, Callable, Literal
@@ -30,8 +35,10 @@ from prompt_toolkit.history import FileHistory
30
35
  from prompt_toolkit.completion import WordCompleter
31
36
  from prompt_toolkit.styles import Style
32
37
  from ptpython.repl import embed
38
+ from rich import pretty
33
39
  from rich.console import Console
34
40
  from rich.theme import Theme
41
+ from tabulate import tabulate
35
42
 
36
43
  # endregion Imports
37
44
 
@@ -49,6 +56,77 @@ def is_num_str(val: str) -> bool:
49
56
  return bool(re.match(r"^-?\d+(\.\d+)?$", val))
50
57
 
51
58
 
59
+ def ls_liah(path: str = "."):
60
+ """Print output similar to using `ls -liah` in the terminal"""
61
+
62
+ files = os.listdir(path)
63
+ files_info = []
64
+
65
+ for file_name in files:
66
+ # Get the full path
67
+ full_path = os.path.join(path, file_name)
68
+
69
+ # Get file stats
70
+ file_stat = os.lstat(full_path)
71
+
72
+ # Get permissions
73
+ permissions = stat.filemode(file_stat.st_mode)
74
+
75
+ # Get number of hard links
76
+ hard_links = file_stat.st_nlink
77
+
78
+ # Get UID and GID, convert to names
79
+ uid_name = pwd.getpwuid(file_stat.st_uid).pw_name
80
+ gid_name = grp.getgrgid(file_stat.st_gid).gr_name
81
+
82
+ # Get file size
83
+ size = file_stat.st_size
84
+
85
+ # Convert size to human-readable form
86
+ size_human = convert_size(size)
87
+
88
+ # Get last modification time
89
+ mtime = time.strftime("%Y-%m-%d %H:%M", time.localtime(file_stat.st_mtime))
90
+
91
+ # Append the information
92
+ files_info.append(
93
+ [
94
+ file_stat.st_ino,
95
+ permissions,
96
+ hard_links,
97
+ uid_name,
98
+ gid_name,
99
+ size_human,
100
+ mtime,
101
+ file_name,
102
+ ]
103
+ )
104
+
105
+ # Print in tabular format
106
+ headers = [
107
+ "Inode",
108
+ "Permissions",
109
+ "Links",
110
+ "UID",
111
+ "GID",
112
+ "Size",
113
+ "Last Modified",
114
+ "Name",
115
+ ]
116
+ print(tabulate(files_info, headers=headers, tablefmt="plain"))
117
+
118
+
119
+ def convert_size(size_bytes):
120
+ """Convert a size in bytes to a human-readable string."""
121
+ if size_bytes == 0:
122
+ return "0B"
123
+ size_name = ("B", "K", "M", "G", "T", "P", "E", "Z", "Y")
124
+ i = int(math.floor(math.log(size_bytes, 1024)))
125
+ p = math.pow(1024, i)
126
+ s = round(size_bytes / p, 2)
127
+ return f"{s}{size_name[i]}"
128
+
129
+
52
130
  @dataclass
53
131
  class ReplTheme(Theme):
54
132
  title: str = "bold cyan"
@@ -332,6 +410,76 @@ class ReplBase:
332
410
  self.commands[cmd_name] = new_cmd
333
411
  return new_cmd
334
412
 
413
+ def setup_cmds(self, *cmd_names: list[str]) -> None:
414
+ """Automatically configure commands based on the provided names
415
+ The ReplCommand objects are populated based on function meta
416
+ data retrieved from the provided function names
417
+ Args:
418
+ cmd_names (list[str]): List of class methods to convert to REPL commands
419
+ """
420
+
421
+ funcs: list[Callable] = [
422
+ getattr(self, name)
423
+ for name in cmd_names
424
+ if hasattr(self, name) and callable(getattr(self, name))
425
+ ]
426
+
427
+ for func in funcs:
428
+ help_text = func.__doc__
429
+ name = func.__name__
430
+ self.add_command(name, func, help_txt=help_text)
431
+
432
+ def warn(self, msg: str) -> None:
433
+ """Print a message to the REPL preformatted as a warning"""
434
+
435
+ self.print(f"[warn]{msg}[/warn]")
436
+
437
+ def pretty_print(self, obj: Any) -> None:
438
+ pretty.pprint(obj)
439
+
440
+ def pwd(self) -> str:
441
+ """Print out the current path location
442
+
443
+ Returns:
444
+ str: The current path
445
+ """
446
+
447
+ self.print(f"Current location: {os.getcwd()}")
448
+ return os.getcwd()
449
+
450
+ def cd(self, path: str = "..") -> str:
451
+ """Move the terminal to a new path location
452
+
453
+ Args:
454
+ path (str, optional): Path to move to. Defaults to "..".
455
+
456
+ Returns:
457
+ str: The new location
458
+ """
459
+
460
+ try:
461
+ os.chdir(path)
462
+ except FileNotFoundError:
463
+ self.warn(
464
+ f"Path: {path} does not exist, remaining in current directory"
465
+ )
466
+ new_pwd = os.getcwd()
467
+ self.print(f"New dir: {new_pwd}")
468
+ return new_pwd
469
+
470
+ def ls(self, path: str = ".") -> list[str]:
471
+ """List metadata about the files/directories at the given path
472
+
473
+ Args:
474
+ path (str, optional): Path to list. Defaults to ".".
475
+
476
+ Returns:
477
+ list[str]: List of file and directory names at the location
478
+ """
479
+
480
+ ls_liah(path)
481
+ return os.listdir(path)
482
+
335
483
  def interactive(self, *args, **kwargs) -> None:
336
484
  """Starts an interactive session from within the class"""
337
485
  if kwargs:
File without changes
File without changes