Partially lockable strings
Project description
lstr: partially lockable Python strings
lstr
is a Python package for partially lockable strings.
Installation
lstr
requires Python 3.8 or later.
pip install lstr
Example
Creating an lstr
from lstr import lstr
greeting = lstr("Hello, world!")
print(greeting) # "Hello, world!"
Writing text
One way to update an lstr
is via write()
. This will replace a specific range of characters with a new string.
For example, to change "Hello" to "Hey", write Hey
at index 0
for length 5
:
from lstr import lstr
greeting = lstr("Hello, world!")
greeting.write("Hey", index=0, length=5)
print(greeting) # "Hey, world!"
Getting help with indexes
To get help figuring out exactly which character is at exactly which index, call repr()
for your lstr
:
from lstr import lstr
greeting = lstr("Hello, world!")
print(repr(greeting))
0 1 2 3 4 5 6 7 8 9 10 11 12
H e l l o , w o r l d !
Substituting text
The second method for updating an lst
is via sub()
. This will replace matches of a regular expression with a new string.
To replace one substring with another:
from lstr import lstr
greeting = lstr("Hello!")
greeting.sub("l", "b")
print(greeting) # "Hebbo!"
To replace each match of a regular expression with a group's value:
from lstr import lstr
document = lstr("How *exciting!* So *bold!*")
document.sub(r"\*([^*]+)\*", r"<em>\g<1></em>")
print(document) # "How <em>exciting!</em> So <em>bold!</em>"
Locking
To prevent any changes to a region of the lst
, lock it via lock()
.
To prevent changes to the word "Hello" in "Hello, world!" create a lock from index 0
for length 5
:
from lstr import lstr
greeting = lstr("Hello, world!")
print(repr(greeting))
# 0 1 2 3 4 5 6 7 8 9 10 11 12
# H e l l o , w o r l d !
greeting.lock(index=0, length=5)
Now any changes to that region will be denied:
from lstr import lstr
greeting = lstr("Hello, world!")
greeting.lock(index=0, length=5)
greeting.sub("Hello", "Hey") # False
print(greeting) # "Hello, world!"
Text outside of that region can still be updated
from lstr import lstr
greeting = lstr("Hello, world!")
greeting.lock(index=0, length=5)
greeting.sub("Hello", "Hey") # False
print(greeting) # "Hello, world!"
greeting.sub("world", "there") # True
print(greeting) # "Hello, there!"
lstr
class
lstr(value: str, locks: List[Lock] = [])
lstr
must be created with a string value, and an optional list of Lock
instances. Additional locks can be added later via the lock()
method.
Equality
lstr
instances are considered equal only if their string value and locks are identical.
lstr("f", locks=[Lock(index=1, length=2)]) == lstr("f", locks=[Lock(index=1, length=2)])
lstr("f", locks=[Lock(index=1, length=2)]) != lstr("f", locks=[Lock(index=3, length=4)])
lstr
and str
instances are considered equal if the string value is identical, regardless of the locks.
lstr("f") == "f"
lstr("f") != "g"
Length
Calling len()
for an lstr
instance will return the length of the string value.
Repr
Calling repr()
for an lstr
instance will return a string describing the index numbers, characters and locks.
from lstr import lstr, Lock
greeting = lstr("Hello, world!", locks=[Lock(index=0, length=5)])
print(repr(greeting))
# 0 1 2 3 4 5 6 7 8 9 10 11 12
# H e l l o , w o r l d !
# ^ ^ ^ ^ ^
Str
Calling str()
for an lstr
instance will return the string value.
can_sub(pattern: str, replacement: str) -> bool
can_sub()
indicates whether or not the specified substitution will succeed for all instances.
can_write(index: int, length: int) -> bool
can_write()
indicates whether or not the specified range can be overwritten.
lock(index: int, length: int) -> None
lock()
describes a new locked range.
sub(pattern: str, replacement: str, allow_partial: bool = False) -> bool
sub()
attempts to substitute all matching patterns with a replacement string.
pattern
is the pattern to search for. This can be a simple string or a regular expression.replacement
is the string to replace matches with. This can be a simple string or an expression expansion to reference a matched group.allow_partial
indicates whether to allow only unlocked matches to be substituted (i.e. a partial update) or to require all matches to be in unlocked ranges (i.e. to force a full update or no update at all).
sub()
returns True
if every matching instance of the pattern could be updated.
write(value: str, index: int, length: int) -> bool
write()
attempts to write a new string into a range.
value
is the string to write.index
is the index to start writing at.length
is the length of the original string to overwrite. This can be0
to insert the string without overwriting. If this length is shorter than the string being written then the base string will become shorter. Likewise, if this length is longer than the string will grow.
write()
returns True
if the range could be written.
Thank you! 🎉
My name is Cariad, and I'm an independent freelance DevOps engineer.
I'd love to spend more time working on projects like this, but--as a freelancer--my income is sporadic and I need to chase gigs that pay the rent.
If this project has value to you, please consider ☕️ sponsoring me. Sponsorships grant me time to work on your wants rather than someone else's.
Thank you! ❤️
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.