Convert SafeString to str

What is the recommended way to convert SafeString to str? It’s needed to generate an OpenAPI schema (the discussion).

So far, I’ve only found two ways:

  • Adding the SafeString with an empty string

    >>> from django.utils.safestring import SafeString
    >>> s = SafeString('abc')
    >>> s + ''
    >>> type(s + '')
    <class 'str'>
  • Use str.__str__()

    >>> from django.utils.safestring import SafeString
    >>> s = SafeString('abc')
    >>> str.__str__(s)
    >>> type(str.__str__(s))
    <class 'str'>

I know using str() wouldn’t work since ccfd129 (due to #27795), and force_str() wouldn’t work either (since SafeString is a subclass of str).

It would be great if anyone could show some examples on Django or any other popular library’s codebase. I mean, at some point, the SafeString instance would be converted to a string, right?

SafeString is a string. That’s the whole concept of it being a subclass. You can use it anywhere you need to use a string.

From my (admittedly superficial) browsing through this, the issue isn’t with SafeString. The root issue is likely that whatever is evaluating this to create the yaml representation is only checking to see if the value is a string and not if the value is a descendant class.

Hi @KenWhitesell , thanks for replying!

So, the issue should be addressed on the library that creates the YAML representation right? I’ve started a discussion about the issue and proposed the workaround. Hope someone on their side will respond to it soon.

How about the conversion? Do you have any recommendations or any references?

There is no “conversion” to be performed.

A SafeString is a string.

Now, there are several functions or operations you can perform on it that return a new string - but those aren’t “conversions”.

For example, some_safe_string.strip() returns a new string with whitespace removed. Also, "".join([some_safe_string]) builds a new string from that single-element list. Or, you could call the __str__ function on the superclass - super(SafeString, some_safe_string).__str__()

On the other hand, all of f"{some_safe_string}", "%s" % some_safe_string and "{}".format(some_safe_string) returns a SafeString.