Skip to content

Commit

Permalink
Add removeprefix and removesuffix
Browse files Browse the repository at this point in the history
Summary: These methods got added in Python 3.9. I've seen two engineers get this wrong without these utilities, so add them. I've also proposed their addition to Starlark in bazelbuild/starlark#185.

Reviewed By: milend

Differential Revision: D27077457

fbshipit-source-id: 6d1eb4a6b1c775fdfa1bcbf62f71809e1dcb44c1
  • Loading branch information
ndmitchell authored and facebook-github-bot committed Mar 16, 2021
1 parent 2875dca commit 7a7ef4b
Showing 1 changed file with 54 additions and 4 deletions.
58 changes: 54 additions & 4 deletions starlark/src/stdlib/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,8 +761,8 @@ pub(crate) fn string_members(builder: &mut GlobalsBuilder) {
/// https://github.com/google/skylark/blob/3705afa472e466b8b061cce44b47c9ddc6db696d/doc/spec.md#string·lstrip
/// ): trim leading whitespaces.
///
/// `S.lstrip()` returns a copy of the string S with leading whitespace
/// removed.
/// `S.lstrip()` returns a copy of the string S with leading whitespace removed.
/// In most cases instead of passing an argument you should use `removeprefix`.
///
/// Examples:
///
Expand Down Expand Up @@ -989,8 +989,8 @@ pub(crate) fn string_members(builder: &mut GlobalsBuilder) {
/// https://github.com/google/skylark/blob/3705afa472e466b8b061cce44b47c9ddc6db696d/doc/spec.md#string·rstrip
/// ): trim trailing whitespace.
///
/// `S.rstrip()` returns a copy of the string S with trailing whitespace
/// removed.
/// `S.rstrip()` returns a copy of the string S with trailing whitespace removed.
/// In most cases instead of passing an argument you should use `removesuffix`.
///
/// Examples:
///
Expand Down Expand Up @@ -1247,6 +1247,56 @@ pub(crate) fn string_members(builder: &mut GlobalsBuilder) {
fn upper(this: &str) -> String {
Ok(this.to_uppercase())
}

/// [string.removeprefix](
/// https://docs.python.org/3.9/library/stdtypes.html#str.removeprefix
/// ): remove a prefix from a string. _Not part of standard Starlark._
///
/// If the string starts with the prefix string, return `string[len(prefix):]`.
/// Otherwise, return a copy of the original string:
///
/// Examples:
///
/// ```
/// # starlark::assert::all_true(r#"
/// "Hello, World!".removeprefix("Hello") == ", World!"
/// "Hello, World!".removeprefix("Goodbye") == "Hello, World!"
/// "Hello".removeprefix("Hello") == ""
/// # "#);
/// ```
fn removeprefix(this: Value<'v>, prefix: &str) -> Value<'v> {
let x = this.unpack_str().unwrap();
if x.starts_with(prefix) && !prefix.is_empty() {
Ok(heap.alloc(&x[prefix.len()..]))
} else {
Ok(this)
}
}

/// [string.removesuffix](
/// https://docs.python.org/3.9/library/stdtypes.html#str.removesuffix
/// ): remove a prefix from a string. _Not part of standard Starlark._
///
/// If the string starts with the prefix string, return `string[len(prefix):]`.
/// Otherwise, return a copy of the original string:
///
/// Examples:
///
/// ```
/// # starlark::assert::all_true(r#"
/// "Hello, World!".removesuffix("World!") == "Hello, "
/// "Hello, World!".removesuffix("World") == "Hello, World!"
/// "Hello".removesuffix("Hello") == ""
/// # "#);
/// ```
fn removesuffix(this: Value<'v>, suffix: &str) -> Value<'v> {
let x = this.unpack_str().unwrap();
if x.ends_with(suffix) && !suffix.is_empty() {
Ok(heap.alloc(&x[..x.len() - suffix.len()]))
} else {
Ok(this)
}
}
}

#[cfg(test)]
Expand Down

0 comments on commit 7a7ef4b

Please sign in to comment.