diff --git a/packages/reflex-base/news/5417.feature.md b/packages/reflex-base/news/5417.feature.md new file mode 100644 index 00000000000..522d7e46f6c --- /dev/null +++ b/packages/reflex-base/news/5417.feature.md @@ -0,0 +1 @@ +`StringVar` now includes `lstrip` and `rstrip` methods. The `strip` method now accepts an optional `chars` argument for consistency with Python’s str API. diff --git a/packages/reflex-base/src/reflex_base/vars/sequence.py b/packages/reflex-base/src/reflex_base/vars/sequence.py index a296f0052b8..df0ccf3f7bb 100644 --- a/packages/reflex-base/src/reflex_base/vars/sequence.py +++ b/packages/reflex-base/src/reflex_base/vars/sequence.py @@ -674,6 +674,20 @@ def lower(self) -> StringVar: """ return string_lower_operation(self) + def lstrip(self, chars: StringVar | str | None = None) -> StringVar: + """Left strip the string. + + Args: + chars: Characters to remove from the left side. If None, strip whitespace. + + Returns: + The string lstrip operation. + """ + if chars is not None and not isinstance(chars, (StringVar, str)): + raise_unsupported_operand_types("lstrip", (type(self), type(chars))) + + return string_lstrip_operation(self, chars) + def upper(self) -> StringVar: """Convert the string to uppercase. @@ -698,13 +712,19 @@ def capitalize(self) -> StringVar: """ return string_capitalize_operation(self) - def strip(self) -> StringVar: + def strip(self, chars: StringVar | str | None = None) -> StringVar: """Strip the string. + Args: + chars: Characters to remove from both ends. If None, strip whitespace. + Returns: The string strip operation. """ - return string_strip_operation(self) + if chars is not None and not isinstance(chars, (StringVar, str)): + raise_unsupported_operand_types("strip", (type(self), type(chars))) + + return string_strip_operation(self, chars) def reversed(self) -> StringVar: """Reverse the string. @@ -714,6 +734,20 @@ def reversed(self) -> StringVar: """ return self.split().reverse().join() + def rstrip(self, chars: StringVar | str | None = None) -> StringVar: + """Right strip the string. + + Args: + chars: Characters to remove from the right side. If None, strip whitespace. + + Returns: + The string rstrip operation. + """ + if chars is not None and not isinstance(chars, (StringVar, str)): + raise_unsupported_operand_types("rstrip", (type(self), type(chars))) + + return string_rstrip_operation(self, chars) + def contains( self, other: StringVar | str, field: StringVar | str | None = None ) -> BooleanVar: @@ -972,16 +1006,48 @@ def string_capitalize_operation(string: StringVar[Any]): @var_operation -def string_strip_operation(string: StringVar[Any]): - """Strip a string. +def string_strip_operation( + string: StringVar[Any], + chars: StringVar[Any] | str | None = None, +): + """Strip a string.""" + if str(chars) == "null": + return var_operation_return(js_expression=f"{string}.trim()", var_type=str) - Args: - string: The string to strip. + return var_operation_return( + js_expression=f"{string}.replace(/^[{chars}]+|[{chars}]+$/g, '')", + var_type=str, + ) - Returns: - The stripped string. - """ - return var_operation_return(js_expression=f"{string}.trim()", var_type=str) + +@var_operation +def string_lstrip_operation( + string: StringVar[Any], + chars: StringVar[Any] | str | None = None, +): + """Left strip a string.""" + if str(chars) == "null": + return var_operation_return(js_expression=f"{string}.trimStart()", var_type=str) + + return var_operation_return( + js_expression=f"{string}.replace(/^[{chars}]+/, '')", + var_type=str, + ) + + +@var_operation +def string_rstrip_operation( + string: StringVar[Any], + chars: StringVar[Any] | str | None = None, +): + """Right strip a string.""" + if str(chars) == "null": + return var_operation_return(js_expression=f"{string}.trimEnd()", var_type=str) + + return var_operation_return( + js_expression=f"{string}.replace(/[{chars}]+$/, '')", + var_type=str, + ) @var_operation diff --git a/tests/units/test_var.py b/tests/units/test_var.py index 6971cdffcd4..5b69a39db66 100644 --- a/tests/units/test_var.py +++ b/tests/units/test_var.py @@ -1001,8 +1001,10 @@ def test_string_operations(): assert str(basic_string.length()) == '"Hello, World!".split("").length' assert str(basic_string.lower()) == '"Hello, World!".toLowerCase()' + assert str(basic_string.lstrip()) == '"Hello, World!".trimStart()' assert str(basic_string.upper()) == '"Hello, World!".toUpperCase()' assert str(basic_string.strip()) == '"Hello, World!".trim()' + assert str(basic_string.rstrip()) == '"Hello, World!".trimEnd()' assert str(basic_string.contains("World")) == '"Hello, World!".includes("World")' assert ( str(basic_string.split(" ").join(",")) == '"Hello, World!".split(" ").join(",")'