こんにちは、
変数sを別の値u '\ xff'に
[テストケース]
@mock_streams('stdout')
def test_puts_with_encoding_type_none_output():
"""
puts() should print unicode output without a stream encoding
"""
s = u"string!" #<====== replace to u"\xff"
output.user = True
sys.stdout.encoding = None
puts(s, show_prefix=False)
eq_(sys.stdout.getvalue(), s + "\n")
[トレースバック]
UnicodeEncodeError: 'ascii'コーデックは位置0〜4の文字をエンコードできません:序数が範囲内にありません(128)
【コメント】
バグのあるポイントはutils.pyの関数 '_encode'にあります。str(msg)を使用して単純にmsgをstrにキャストしないでください。
def _encode(msg, stream):
if isinstance(msg, unicode) and hasattr(stream, 'encoding') and not stream.encoding is None:
return msg.encode(stream.encoding)
else:
return str(msg) #<========== buggy point
誰も気にしますか?
うん、 return str(msg)
をreturn msg
すると、テストを中断することなく問題が解決するようです。 しかし、そもそもなぜこのキャストが必要だったのでしょうか。
今これを変更することが理にかなっているのか、絶対にわかりません。 誰かのコードを完全に壊すことはありませんが、基本的には文字列ではないものをputs
て、意味のあるものを引き出すことができます。
>>> class Foo(object):
... def __str__(self): return "The best Foo in the world"
...
>>> from fabric.api import puts
>>> puts(Foo())
The best Foo in the world
これを使用するコードがあると思います(githubでこれを検索することはできませんので、例を探すつもりはありません)。
ただし、エンコーディングセットがなく、Unicodeを使用すると、 puts
がクラッシュするのは正しいと思います。
今のところこれに対処するための最悪の方法は、問題のある行をこのブロックに単純に拡張することです。
try:
return str(msg) # Original behavior added for 'reasons'
except UnicodeDecodeError:
return msg # Best-effort fallback
このように、文字列へのキャストについて私たちが持っていた以前の理由は何でも機能し続けますが、議論中のバグのあるケースは「まあ、これが何であるかはわかりませんが、 str()
できません、そのままパイプに押し込みます」
sudo
メソッドの実行中に同様の問題が発生し、 io.py
self.stream.write(text)
で例外が発生しました。 Unicodeの問題に進展はありますか?
最も参考になるコメント
誰も気にしますか?