2013-11-25 00:26:22 +01:00
|
|
|
"""Stuff that differs in different Python versions and platform
|
|
|
|
distributions."""
|
2014-09-18 14:30:03 +02:00
|
|
|
from __future__ import absolute_import, division
|
2009-11-20 08:10:46 +01:00
|
|
|
|
2012-08-05 03:48:16 +02:00
|
|
|
import os
|
2010-06-03 20:44:34 +02:00
|
|
|
import sys
|
|
|
|
|
2014-09-12 01:16:31 +02:00
|
|
|
from pip._vendor.six import text_type
|
2014-01-27 20:40:32 +01:00
|
|
|
|
2014-12-10 01:40:05 +01:00
|
|
|
try:
|
|
|
|
import ipaddress
|
|
|
|
except ImportError:
|
2015-05-23 18:59:53 +02:00
|
|
|
try:
|
|
|
|
from pip._vendor import ipaddress
|
|
|
|
except ImportError:
|
|
|
|
import ipaddr as ipaddress
|
|
|
|
ipaddress.ip_address = ipaddress.IPAddress
|
|
|
|
ipaddress.ip_network = ipaddress.IPNetwork
|
2014-12-10 01:40:05 +01:00
|
|
|
|
2014-08-31 01:52:28 +02:00
|
|
|
|
2014-09-12 01:16:31 +02:00
|
|
|
__all__ = [
|
2017-03-18 18:22:44 +01:00
|
|
|
"ipaddress", "uses_pycache", "console_to_str", "native_str",
|
2017-03-18 20:35:15 +01:00
|
|
|
"get_path_uid", "stdlib_pkgs", "WINDOWS", "samefile",
|
2014-09-12 01:16:31 +02:00
|
|
|
]
|
|
|
|
|
|
|
|
|
2015-05-02 02:45:58 +02:00
|
|
|
if sys.version_info >= (3, 4):
|
|
|
|
uses_pycache = True
|
|
|
|
from importlib.util import cache_from_source
|
|
|
|
else:
|
|
|
|
import imp
|
|
|
|
uses_pycache = hasattr(imp, 'cache_from_source')
|
|
|
|
if uses_pycache:
|
|
|
|
cache_from_source = imp.cache_from_source
|
|
|
|
else:
|
|
|
|
cache_from_source = None
|
2014-09-12 01:16:31 +02:00
|
|
|
|
|
|
|
|
2011-03-15 20:49:48 +01:00
|
|
|
if sys.version_info >= (3,):
|
2011-03-23 00:24:25 +01:00
|
|
|
def console_to_str(s):
|
2011-10-26 06:56:36 +02:00
|
|
|
try:
|
2014-09-12 01:13:42 +02:00
|
|
|
return s.decode(sys.__stdout__.encoding)
|
2011-10-26 06:56:36 +02:00
|
|
|
except UnicodeDecodeError:
|
|
|
|
return s.decode('utf_8')
|
|
|
|
|
2014-09-02 03:43:32 +02:00
|
|
|
def native_str(s, replace=False):
|
2014-07-11 05:50:43 +02:00
|
|
|
if isinstance(s, bytes):
|
2014-09-02 03:43:32 +02:00
|
|
|
return s.decode('utf-8', 'replace' if replace else 'strict')
|
2014-07-11 05:50:43 +02:00
|
|
|
return s
|
|
|
|
|
2011-03-15 20:49:48 +01:00
|
|
|
else:
|
2011-03-23 00:24:25 +01:00
|
|
|
def console_to_str(s):
|
|
|
|
return s
|
2011-12-27 18:26:33 +01:00
|
|
|
|
2014-09-02 03:43:32 +02:00
|
|
|
def native_str(s, replace=False):
|
|
|
|
# Replace is ignored -- unicode to UTF-8 can't fail
|
2014-09-12 01:16:31 +02:00
|
|
|
if isinstance(s, text_type):
|
2014-07-11 05:50:43 +02:00
|
|
|
return s.encode('utf-8')
|
|
|
|
return s
|
|
|
|
|
2011-03-15 20:49:48 +01:00
|
|
|
|
2013-11-25 00:26:22 +01:00
|
|
|
def get_path_uid(path):
|
|
|
|
"""
|
|
|
|
Return path's uid.
|
|
|
|
|
2014-01-27 15:07:10 +01:00
|
|
|
Does not follow symlinks:
|
|
|
|
https://github.com/pypa/pip/pull/935#discussion_r5307003
|
2013-11-25 00:26:22 +01:00
|
|
|
|
2014-05-14 05:10:06 +02:00
|
|
|
Placed this function in compat due to differences on AIX and
|
2014-01-27 15:07:10 +01:00
|
|
|
Jython, that should eventually go away.
|
2013-11-25 00:26:22 +01:00
|
|
|
|
|
|
|
:raises OSError: When path is a symlink or can't be read.
|
|
|
|
"""
|
|
|
|
if hasattr(os, 'O_NOFOLLOW'):
|
|
|
|
fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW)
|
|
|
|
file_uid = os.fstat(fd).st_uid
|
|
|
|
os.close(fd)
|
|
|
|
else: # AIX and Jython
|
2016-06-10 21:27:07 +02:00
|
|
|
# WARNING: time of check vulnerability, but best we can do w/o NOFOLLOW
|
2013-11-25 00:26:22 +01:00
|
|
|
if not os.path.islink(path):
|
|
|
|
# older versions of Jython don't have `os.fstat`
|
|
|
|
file_uid = os.stat(path).st_uid
|
|
|
|
else:
|
|
|
|
# raise OSError for parity with os.O_NOFOLLOW above
|
2014-01-27 15:07:10 +01:00
|
|
|
raise OSError(
|
|
|
|
"%s is a symlink; Will not return uid for symlinks" % path
|
|
|
|
)
|
2013-11-25 00:26:22 +01:00
|
|
|
return file_uid
|
2014-03-01 05:09:26 +01:00
|
|
|
|
|
|
|
|
2015-09-29 21:31:27 +02:00
|
|
|
def expanduser(path):
|
|
|
|
"""
|
|
|
|
Expand ~ and ~user constructions.
|
|
|
|
|
|
|
|
Includes a workaround for http://bugs.python.org/issue14768
|
|
|
|
"""
|
|
|
|
expanded = os.path.expanduser(path)
|
|
|
|
if path.startswith('~/') and expanded.startswith('//'):
|
|
|
|
expanded = expanded[1:]
|
|
|
|
return expanded
|
|
|
|
|
|
|
|
|
2014-03-01 05:09:26 +01:00
|
|
|
# packages in the stdlib that may have installation metadata, but should not be
|
|
|
|
# considered 'installed'. this theoretically could be determined based on
|
|
|
|
# dist.location (py27:`sysconfig.get_paths()['stdlib']`,
|
|
|
|
# py26:sysconfig.get_config_vars('LIBDEST')), but fear platform variation may
|
|
|
|
# make this ineffective, so hard-coding
|
2017-03-18 20:19:44 +01:00
|
|
|
stdlib_pkgs = {"python", "wsgiref", "argparse"}
|
2014-06-26 14:15:31 +02:00
|
|
|
|
2014-09-12 01:16:31 +02:00
|
|
|
|
2014-06-26 14:15:31 +02:00
|
|
|
# windows detection, covers cpython and ironpython
|
2015-02-24 13:46:10 +01:00
|
|
|
WINDOWS = (sys.platform.startswith("win") or
|
|
|
|
(sys.platform == 'cli' and os.name == 'nt'))
|
2017-03-18 20:35:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
def samefile(file1, file2):
|
|
|
|
"""Provide an alternative for os.path.samefile on Windows/Python2"""
|
|
|
|
if hasattr(os.path, 'samefile'):
|
|
|
|
return os.path.samefile(file1, file2)
|
|
|
|
else:
|
|
|
|
path1 = os.path.normcase(os.path.abspath(file1))
|
|
|
|
path2 = os.path.normcase(os.path.abspath(file2))
|
|
|
|
return path1 == path2
|