{{{
if six.PY3:
__bytes__ = serialize
else:
__str__ = serialize
}}}
Because `__str__` is not defined when `six.PY3` is True, calling
`str(response_object)` falls back to `__repr__` on Python 3. However,
`__str__` is defined on Python 2, and it returns the full HTTP message.
It seems like bad idea to have the output of the "convert to string"
action be different based on Python version, as it makes multi-version
code difficult to implement and debug.
--
Ticket URL: <https://code.djangoproject.com/ticket/26549>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0
Comment:
What do you think the correct resolution is? The commit where that branch
was introduced is e04230e2e406dcf74eeec8d3c95c84362c7da780.
--
Ticket URL: <https://code.djangoproject.com/ticket/26549#comment:1>
Comment (by coredumperror):
I would remove the `else`, so that `__str__` is defined the same way for
both Python2 and Python 3. Heck, the `if` isn't even needed, since there's
no harm in defining `__bytes__` on Python 2, as it won't do anything. So
I'd ultimately replace the entire block with
{{{
__bytes__ = serialize
__str__ = serialize
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/26549#comment:2>
Comment (by claudep):
Having a `__str__` method on Python 3 which returns bytes might be
problematic.
From the
[https://docs.python.org/3/reference/datamodel.html#object.__str__ Python
3 docs]: ` The return value must be a string object.`
--
Ticket URL: <https://code.djangoproject.com/ticket/26549#comment:3>
Comment (by coredumperror):
Ah, *that's* why the if check is there. My inexperience with Python 3 is
showing...
Would it be possible to convert the content data in the response to
unicode for `__str__`? I'm not particularly familiar with Python 3, so I'm
not sure if this would be particularly easy.
--
Ticket URL: <https://code.djangoproject.com/ticket/26549#comment:4>
Comment (by aaugustin):
Yes, you just need:
{{{
def __str__(self):
return bytes(self).decode(self.charset)
}}}
I don't think this is a good idea, though, because:
- you aren't supposed to do anything with this value other than show it to
a human
- full HTTP responses aren't particularly human friendly
What's the use case here?
--
Ticket URL: <https://code.djangoproject.com/ticket/26549#comment:5>
Comment (by coredumperror):
The place I'm using this is in some tests where I need to check the HTML
content of the response. `self.assertContains()` isn't sufficient, because
that cares about the whitespace, and the templates render a lot of
extraneous whitespace. So I use `self.assertInHTML()` instead.
Unfortunately, `assertInHTML()` doesn't accept an HttpResponse object, so
I have to send it a string.
Is there a better way to do this with built-in django testing tools?
--
Ticket URL: <https://code.djangoproject.com/ticket/26549#comment:6>
Comment (by aaugustin):
I see. I guess I'd just use `content =
response.content.decode(response.charset)`.
--
Ticket URL: <https://code.djangoproject.com/ticket/26549#comment:7>
Comment (by coredumperror):
I ended up going with `content = str(response.content)`, as that was the
only way I found to make the test code compatible with both Python 2 and
3. I think your way probably works for both too, but I'm not really sure.
The `decode()` and `encode()` functions have been the bane of my existence
for years, because I never get them right.
--
Ticket URL: <https://code.djangoproject.com/ticket/26549#comment:8>
* status: new => closed
* resolution: => wontfix
--
Ticket URL: <https://code.djangoproject.com/ticket/26549#comment:9>
Comment (by aaugustin):
> The decode() and encode() functions have been the bane of my existence
for years, because I never get them right.
That's the reason why Python 3 exists... Stop caring about Python 2 now
;-)
--
Ticket URL: <https://code.djangoproject.com/ticket/26549#comment:10>
Comment (by coredumperror):
If only it were that easy...
--
Ticket URL: <https://code.djangoproject.com/ticket/26549#comment:11>