getsentry/raven-python — pull request #322 by carljm (2013-06-14 02:55:12+00:00)
Title: Fix "AttributeError: 'str' object has no attribute 'decode'" in Python 3.3

When running `raven test` under Python 3.3, I get the following traceback:

```
$ raven test
Using DSN configuration:
https://...:...@app.getsentry.com/...

Client configuration:
servers : ['https://app.getsentry.com/api/store/']
project : ...
public_key : ...
secret_key : ...

Sending a test message...
Traceback (most recent call last):
File "/home/carljm/.venvs/raven33/bin/raven", line 9, in
load_entry_point('raven==3.3.7', 'console_scripts', 'raven')()
File "/home/carljm/projects/sentry/raven-python/raven/scripts/runner.py", line 112, in main
send_test_message(client, opts.__dict__)
File "/home/carljm/projects/sentry/raven-python/raven/scripts/runner.py", line 77, in send_test_message
'loadavg': get_loadavg(),
File "/home/carljm/projects/sentry/raven-python/raven/base.py", line 577, in captureMessage
return self.capture('raven.events.Message', message=message, **kwargs)
File "/home/carljm/projects/sentry/raven-python/raven/base.py", line 459, in capture
**kwargs)
File "/home/carljm/projects/sentry/raven-python/raven/base.py", line 303, in build_msg
transformer=self.transform)
File "/home/carljm/projects/sentry/raven-python/raven/utils/stacks.py", line 219, in get_stack_info
pre_context, context_line, post_context = get_lines_from_file(abs_path, lineno, 5, loader, module_name)
File "/home/carljm/projects/sentry/raven-python/raven/utils/stacks.py", line 64, in get_lines_from_file
match = _coding_re.search(line.decode('ascii')) # let's assume ascii
AttributeError: 'str' object has no attribute 'decode'
```

This seems to be because `loader.get_source()` is available in `get_lines_from_file`, and it returns a string, not bytes. Attempting to call `line.decode('ascii')` on a line from that source string raises the `AttributeError` because strings (in Python 3) don't have a `decode` method.

When I run `raven test` under Python 2.7 or 3.2, `loader` in that function is `None`, so the source is gotten instead by opening the file in `rb` mode, which returns bytes, thus the decode call succeeds.

With the attached fix, which decodes the source only in the case where it was read directly from the filesystem, not from a loader, `raven test` works for me in 2.7, 3.2, and 3.3. (It fails in 2.6 for me either with or without this fix, with some apparently-unrelated urlopen error).

This fix would fail if there are scenarios in which `loader.get_source` returns bytes instead of a string. My testing didn't find such a scenario, but that doesn't mean it doesn't exist.