stringz 0.1.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.
stringz/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from ._truncated_string import TStr, trunc_str # noqa
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
from typing import Self, SupportsIndex
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def trunc_str(
|
|
5
|
+
text: str,
|
|
6
|
+
max_chars: int,
|
|
7
|
+
placeholder: str = "...",
|
|
8
|
+
) -> str:
|
|
9
|
+
"""A function that truncates a string to a maximum number of characters,
|
|
10
|
+
appending a placeholder if truncation occurs.
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
Basic usage:
|
|
14
|
+
|
|
15
|
+
>>> from stringz import trunc_str
|
|
16
|
+
>>> trunc_str("hello world", max_chars=10)
|
|
17
|
+
'hello w...'
|
|
18
|
+
|
|
19
|
+
No truncation needed:
|
|
20
|
+
|
|
21
|
+
>>> trunc_str("short", max_chars=10)
|
|
22
|
+
'short'
|
|
23
|
+
|
|
24
|
+
Custom placeholder:
|
|
25
|
+
|
|
26
|
+
>>> trunc_str("hello world", max_chars=10, placeholder=">>")
|
|
27
|
+
'hello wo>>'
|
|
28
|
+
|
|
29
|
+
Empty placeholder:
|
|
30
|
+
|
|
31
|
+
>>> trunc_str("hello world", max_chars=5, placeholder="")
|
|
32
|
+
'hello'
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
text: The string to be truncated.
|
|
36
|
+
max_chars: The maximum number of characters allowed in the output string.
|
|
37
|
+
placeholder: The string to append if truncation occurs. Default is '...'.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
The truncated string, if necessary, with the placeholder appended.
|
|
41
|
+
|
|
42
|
+
Raises:
|
|
43
|
+
TypeError: If text is not a string.
|
|
44
|
+
ValueError: If max_chars is not a positive integer or if placeholder length is greater than or
|
|
45
|
+
equal to max_chars.
|
|
46
|
+
TypeError: If placeholder is not a string.
|
|
47
|
+
ValueError: If placeholder length is greater than or equal to max_chars.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
# ====> VALIDATION
|
|
51
|
+
if not isinstance(text, str):
|
|
52
|
+
_err: str = f"text must be a string, not {type(text).__name__}"
|
|
53
|
+
raise TypeError(_err)
|
|
54
|
+
if not isinstance(max_chars, int) or max_chars <= 0:
|
|
55
|
+
_err: str = f"max_chars must be a positive integer, got {max_chars}"
|
|
56
|
+
raise ValueError(_err)
|
|
57
|
+
if not isinstance(placeholder, str):
|
|
58
|
+
_err: str = f"placeholder must be a string, not {type(placeholder).__name__}"
|
|
59
|
+
raise TypeError(_err)
|
|
60
|
+
if len(placeholder) >= max_chars:
|
|
61
|
+
_err: str = f"placeholder length ({len(placeholder)}) must be smaller than max_chars ({max_chars})"
|
|
62
|
+
raise ValueError(_err)
|
|
63
|
+
|
|
64
|
+
# ====> TRUNCATE
|
|
65
|
+
if len(text) <= max_chars:
|
|
66
|
+
return text
|
|
67
|
+
return text[: max_chars - len(placeholder)] + placeholder
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class TStr(str):
|
|
71
|
+
"""A string subclass that automatically truncates its content to a maximum length when created or modified through
|
|
72
|
+
string operations. The TStr class uses the `trunc_str` function for truncation under the hood.
|
|
73
|
+
|
|
74
|
+
Example:
|
|
75
|
+
Basic creation:
|
|
76
|
+
|
|
77
|
+
>>> from stringz import TStr
|
|
78
|
+
>>> s = TStr("hello world", max_chars=10)
|
|
79
|
+
>>> print(s)
|
|
80
|
+
hello w...
|
|
81
|
+
>>> len(s)
|
|
82
|
+
10
|
|
83
|
+
|
|
84
|
+
String operations maintain TStr type and truncation:
|
|
85
|
+
|
|
86
|
+
>>> s1 = TStr("hello", max_chars=10)
|
|
87
|
+
>>> s2 = s1 + " world"
|
|
88
|
+
>>> type(s2)
|
|
89
|
+
<class 'stringz._truncated_string.TStr'>
|
|
90
|
+
>>> print(s2)
|
|
91
|
+
hello w...
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
__slots__ = (
|
|
95
|
+
"max_chars",
|
|
96
|
+
"placeholder",
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
max_chars: int | None
|
|
100
|
+
placeholder: str
|
|
101
|
+
|
|
102
|
+
def __new__(
|
|
103
|
+
cls,
|
|
104
|
+
value: str,
|
|
105
|
+
max_chars: int | None = None,
|
|
106
|
+
placeholder: str = "...",
|
|
107
|
+
) -> Self:
|
|
108
|
+
"""Create a new TStr instance.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
value: The initial string value.
|
|
112
|
+
max_chars: Maximum number of characters. If None, no truncation occurs.
|
|
113
|
+
placeholder: String to append when truncating. Default is '...'.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
A new TStr instance with the specified truncation settings.
|
|
117
|
+
"""
|
|
118
|
+
if max_chars is not None:
|
|
119
|
+
value = trunc_str(
|
|
120
|
+
text=value,
|
|
121
|
+
max_chars=max_chars,
|
|
122
|
+
placeholder=placeholder,
|
|
123
|
+
)
|
|
124
|
+
instance = super().__new__(cls, value)
|
|
125
|
+
instance.max_chars = max_chars
|
|
126
|
+
instance.placeholder = placeholder
|
|
127
|
+
return instance
|
|
128
|
+
|
|
129
|
+
def __add__(self, other: str) -> Self:
|
|
130
|
+
result = super().__add__(other)
|
|
131
|
+
return type(self)(result, self.max_chars)
|
|
132
|
+
|
|
133
|
+
def __mul__(self, other: SupportsIndex) -> Self:
|
|
134
|
+
result = super().__mul__(other)
|
|
135
|
+
return type(self)(result, self.max_chars)
|
|
136
|
+
|
|
137
|
+
def __radd__(self, other: str) -> Self:
|
|
138
|
+
result = other + str(self)
|
|
139
|
+
return type(self)(result, self.max_chars)
|
|
140
|
+
|
|
141
|
+
def __rmul__(self, other: SupportsIndex) -> Self:
|
|
142
|
+
result = other * str(self)
|
|
143
|
+
return type(self)(result, self.max_chars)
|
|
144
|
+
|
|
145
|
+
def __mod__(self, other) -> Self:
|
|
146
|
+
result = super().__mod__(other)
|
|
147
|
+
return type(self)(result, self.max_chars)
|
|
148
|
+
|
|
149
|
+
def __rmod__(self, other) -> Self:
|
|
150
|
+
result = other % str(self)
|
|
151
|
+
return type(self)(result, self.max_chars)
|
|
152
|
+
|
|
153
|
+
def __getitem__(self, key) -> str | Self:
|
|
154
|
+
result = super().__getitem__(key)
|
|
155
|
+
if isinstance(key, int):
|
|
156
|
+
return result
|
|
157
|
+
return type(self)(result, self.max_chars)
|
|
158
|
+
|
|
159
|
+
def __format__(self, format_spec: str) -> str:
|
|
160
|
+
return super().__format__(format_spec)
|
|
161
|
+
|
|
162
|
+
def __repr__(self) -> str:
|
|
163
|
+
return f"TStr({super().__repr__()}, max_chars={self.max_chars}, placeholder={self.placeholder})"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: stringz
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Utilities library for working with strings
|
|
5
|
+
Project-URL: Changelog, https://github.com/johandielangman/stringz/blob/main/CHANGELOG.md
|
|
6
|
+
Project-URL: Documentation, https://johandielangman.github.io/stringz/
|
|
7
|
+
Project-URL: Issues, https://github.com/johandielangman/stringz/issues
|
|
8
|
+
Project-URL: Source, https://github.com/johandielangman/stringz
|
|
9
|
+
Author-email: Johandielangman <johan@datatreehouse.org>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE.txt
|
|
12
|
+
Classifier: Operating System :: MacOS
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Programming Language :: Python
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
<p align="center">
|
|
25
|
+
<a href="https://johandielangman.github.io/stringz/">
|
|
26
|
+
<img src="https://raw.githubusercontent.com/johandielangman/stringz/main/docs/static/images/banner.svg" alt="stringz">
|
|
27
|
+
</a>
|
|
28
|
+
</p>
|
|
29
|
+
<p align="center">
|
|
30
|
+
<em>Utilities library for working with strings.</em>
|
|
31
|
+
</p>
|
|
32
|
+
<p align="center">
|
|
33
|
+
<a href="https://pypi.org/project/stringz"><img src="https://img.shields.io/pypi/v/stringz.svg" alt="PyPI - Version"></a>
|
|
34
|
+
<a href="https://pypi.org/project/stringz"><img src="https://img.shields.io/pypi/pyversions/stringz.svg" alt="PyPI - Python Version"></a>
|
|
35
|
+
<a href="https://github.com/johandielangman/stringz/actions/workflows/ci.yml"><img src="https://github.com/johandielangman/stringz/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
36
|
+
<a href="https://codecov.io/gh/johandielangman/stringz"><img src="https://codecov.io/gh/johandielangman/stringz/graph/badge.svg" alt="codecov"></a>
|
|
37
|
+
<a href="https://johandielangman.github.io/stringz/"><img src="https://img.shields.io/badge/docs-latest-blue" alt="Docs"></a>
|
|
38
|
+
</p>
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
Simply install this amazing utilities package:
|
|
43
|
+
|
|
44
|
+
``` console
|
|
45
|
+
uv add stringz
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
And immediately get the benefits
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from stringz import pretty_str, ding
|
|
52
|
+
|
|
53
|
+
result = pretty_str("Hello world!", max_chars=10)
|
|
54
|
+
print(result) # Output: 'Hello w...'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Roadmap
|
|
58
|
+
|
|
59
|
+
only the future will know!
|
|
60
|
+
|
|
61
|
+
- [x] Pretty truncation and truncation string type
|
|
62
|
+
- [ ] `mask` for sensitive information masking
|
|
63
|
+
- [ ] converters (`to_snake`, `to_camel`, etc)
|
|
64
|
+
- [ ] `join_human` that joins using Oxford comma
|
|
65
|
+
- [ ] `ordinal(22)` should give `22nd`
|
|
66
|
+
- [ ] `pluralize("box", n)` gives "boxes"... maybe
|
|
67
|
+
- [ ] `slugify`
|
|
68
|
+
- [ ] `is_blank`
|
|
69
|
+
|
|
70
|
+
## License
|
|
71
|
+
|
|
72
|
+
`stringz` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
stringz/__init__.py,sha256=UAMKx_eZUSe8EFQ8XwXt8yIWQ0-A7q4eb0NApPqCtrc,55
|
|
2
|
+
stringz/_truncated_string.py,sha256=ZoCCpw_9hrGwamIk9uZBrikFaif-i7zgdUzwr7_briw,5046
|
|
3
|
+
stringz-0.1.1.dist-info/METADATA,sha256=rK65iaYiT3n0No2S1_LLMLspP4RPFm9iVX9JSS3DsIs,2771
|
|
4
|
+
stringz-0.1.1.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
|
|
5
|
+
stringz-0.1.1.dist-info/licenses/LICENSE.txt,sha256=x7yQuGcgYfBt-59XVxvZEzDp-rw8aRlEzu_mcxSNlKA,1080
|
|
6
|
+
stringz-0.1.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026-present Johandielangman
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
6
|
+
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
|
9
|
+
following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
12
|
+
portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
|
15
|
+
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
|
16
|
+
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
18
|
+
USE OR OTHER DEALINGS IN THE SOFTWARE.
|