diff options
author | Stefan Scherfke <stefan@sofa-rockers.org> | 2013-11-21 11:06:27 +0100 |
---|---|---|
committer | Donald Stufft <donald@stufft.io> | 2013-12-20 12:49:52 -0500 |
commit | b878de0fe19e9b1aed8202cc384b180418938265 (patch) | |
tree | c0b2d79b1221bb2e5b705ebc4a870f6592ca3e07 /pip/req.py | |
parent | d4bcee7bdec788895c362536e84e864a8a0cfba8 (diff) | |
download | pip-b878de0fe19e9b1aed8202cc384b180418938265.tar.gz |
Try utf-8, the system’s default encoding, and latin1 when reading egg_info-files to avoid UnicodeDecodeErrors at the installation of a package.
Diffstat (limited to 'pip/req.py')
-rw-r--r-- | pip/req.py | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/pip/req.py b/pip/req.py index bf6d66636..f05aeeb66 100644 --- a/pip/req.py +++ b/pip/req.py @@ -1,6 +1,7 @@ from email.parser import FeedParser import os import imp +import locale import pkg_resources import re import sys @@ -35,6 +36,30 @@ import pip.wheel from pip.wheel import move_wheel_files, Wheel, wheel_ext +def read_text_file(filename): + """Return the contents of *filename*. + + Try to decode the file contents with utf-8, the preffered system encoding + (e.g., cp1252 on some Windows machines) and latin1, in that order. Decoding + a byte string with latin1 will never raise an error. In the worst case, the + returned string will contain some garbage characters. + + """ + with open(filename, 'rb') as fp: + data = fp.read() + + encodings = ['utf-8', locale.getpreferredencoding(False), 'latin1'] + for enc in encodings: + try: + data = data.decode(enc) + except UnicodeDecodeError: + continue + break + + assert type(data) != bytes # Latin1 should have worked. + return data + + class InstallRequirement(object): def __init__(self, req, comes_from, source_dir=None, editable=False, @@ -322,9 +347,7 @@ exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\\r\\n', filename = self.egg_info_path(filename) if not os.path.exists(filename): return None - fp = open(filename, 'r') - data = fp.read() - fp.close() + data = read_text_file(filename) return data def egg_info_path(self, filename): |