Skip to content

Commit 3c475cf

Browse files
committed
feat(disk): add shorten_path() for zsh-style path abbreviation
Reduce every parent path component to its first character while keeping the basename in full, the way the zsh prompt shortens a long working directory. Pure string transform, no filesystem access. Unit-tested.
1 parent 9cc44c7 commit 3c475cf

3 files changed

Lines changed: 64 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010

1111
### Added
1212

13+
* disk.py: `shorten_path()` abbreviates a path for display by reducing every parent component to its first character (zsh-style), keeping the basename in full
1314
* redfish.py: `get_auth_header()` builds the request authentication header, reusing a cached session token to avoid creating a new controller session on every request, and falling back to HTTP Basic auth
1415
* redfish.py: `get_chassis_power_powercontrol()` parses a power control (overall power consumption) entry for health monitoring and reporting
1516
* redfish.py: `get_manager()` parses a manager (BMC) resource for health monitoring and identification

disk.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"""
1414

1515
__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
16-
__version__ = '2026060601'
16+
__version__ = '2026060801'
1717

1818
import csv
1919
import os
@@ -693,6 +693,36 @@ def rm_file(filename):
693693
return False, f'Unknown error deleting {filename}: {e}'
694694

695695

696+
def shorten_path(path):
697+
"""
698+
Shorten a path for display.
699+
700+
Abbreviate a slash-separated path by reducing every component except the last one to its
701+
first character, the way the zsh prompt shortens a long working directory. The last
702+
component is kept in full because it usually carries the identifying information. This is
703+
a pure string transformation; the path is not resolved and the filesystem is not touched.
704+
705+
### Parameters
706+
- **path** (`str`): A slash-separated path, for example `/etc/pki/tls/certs/002c0b4f.0`.
707+
708+
### Returns
709+
- **str**: The abbreviated path, for example `/e/p/t/c/002c0b4f.0`. A value without a
710+
slash (a bare basename, an empty string, a sentinel like `-`) is returned unchanged.
711+
712+
### Example
713+
>>> shorten_path('/etc/pki/tls/certs/002c0b4f.0')
714+
'/e/p/t/c/002c0b4f.0'
715+
716+
>>> shorten_path('index.php')
717+
'index.php'
718+
"""
719+
if not path or '/' not in path:
720+
return path
721+
head, _, tail = path.rpartition('/')
722+
abbrev = '/'.join(part[:1] for part in head.split('/'))
723+
return f'{abbrev}/{tail}'
724+
725+
696726
def udevadm(device, _property):
697727
"""
698728
Run `udevadm info` and extract a specific property manually.

tests/disk/unit-test/run

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ class TestTreeOps(unittest.TestCase):
112112
disk.write_file(os.path.join(src, 'a.txt'), 'x')
113113

114114
dst_file = os.path.join(self.base, 'a-copy.txt')
115-
self.assertEqual(disk.copy_file(os.path.join(src, 'a.txt'), dst_file), (True, None))
115+
self.assertEqual(
116+
disk.copy_file(os.path.join(src, 'a.txt'), dst_file), (True, None)
117+
)
116118
self.assertTrue(os.path.isfile(dst_file))
117119

118120
dst_dir = os.path.join(self.base, 'dst')
@@ -146,5 +148,34 @@ class TestHostHelpers(unittest.TestCase):
146148
self.assertIsInstance(disk.get_block_devices(), list)
147149

148150

151+
class TestShortenPath(unittest.TestCase):
152+
def test_abbreviates_parents_keeps_basename(self):
153+
self.assertEqual(
154+
disk.shorten_path('/etc/pki/tls/certs/002c0b4f.0'),
155+
'/e/p/t/c/002c0b4f.0',
156+
)
157+
self.assertEqual(
158+
disk.shorten_path('/usr/share/icingaweb2/public/index.php'),
159+
'/u/s/i/p/index.php',
160+
)
161+
162+
def test_two_segment_path(self):
163+
self.assertEqual(disk.shorten_path('/srv/index.php'), '/s/index.php')
164+
165+
def test_top_level_file_stays(self):
166+
self.assertEqual(disk.shorten_path('/index.php'), '/index.php')
167+
168+
def test_relative_path(self):
169+
self.assertEqual(disk.shorten_path('relative/path/file'), 'r/p/file')
170+
171+
def test_no_slash_passthrough(self):
172+
self.assertEqual(disk.shorten_path('index.php'), 'index.php')
173+
self.assertEqual(disk.shorten_path('-'), '-')
174+
self.assertEqual(disk.shorten_path(''), '')
175+
176+
def test_root_stays(self):
177+
self.assertEqual(disk.shorten_path('/'), '/')
178+
179+
149180
if __name__ == '__main__':
150181
unittest.main()

0 commit comments

Comments
 (0)