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