# -*- coding: utf-8 -*- # Copyright (C) 2012 Anaconda, Inc # SPDX-License-Identifier: BSD-3-Clause # Try to keep compat small because it's imported by everything # What is compat, and what isn't? # If a piece of code is "general" and used in multiple modules, it goes here. # If it's only used in one module, keep it in that module, preferably near the top. # This module should contain ONLY stdlib imports. from __future__ import absolute_import, division, print_function, unicode_literals from itertools import chain from operator import methodcaller import sys from tempfile import mkdtemp on_win = bool(sys.platform == "win32") on_mac = bool(sys.platform == "darwin") on_linux = bool(sys.platform == "linux") FILESYSTEM_ENCODING = sys.getfilesystemencoding() # Control some tweakables that will be removed finally. ENCODE_ENVIRONMENT = True ENCODE_ARGS = False def encode_for_env_var(value) -> str: """Environment names and values need to be string.""" if isinstance(value, str): return value elif isinstance(value, bytes): return value.decode() return str(value) def encode_environment(env): if ENCODE_ENVIRONMENT: env = {encode_for_env_var(k): encode_for_env_var(v) for k, v in env.items()} return env def encode_arguments(arguments): if ENCODE_ARGS: arguments = {encode_for_env_var(arg) for arg in arguments} return arguments from collections.abc import Iterable from io import StringIO def isiterable(obj): return not isinstance(obj, str) and isinstance(obj, Iterable) # ############################# # other # ############################# from collections import OrderedDict as odict # NOQA from io import open as io_open # NOQA def open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True): if 'b' in mode: return io_open(file, str(mode), buffering=buffering, errors=errors, newline=newline, closefd=closefd) else: return io_open(file, str(mode), buffering=buffering, encoding=encoding or 'utf-8', errors=errors, newline=newline, closefd=closefd) def six_with_metaclass(meta, *bases): """Create a base class with a metaclass.""" # This requires a bit of explanation: the basic idea is to make a dummy # metaclass for one level of class instantiation that replaces itself with # the actual metaclass. class metaclass(type): def __new__(cls, name, this_bases, d): return meta(name, bases, d) @classmethod def __prepare__(cls, name, this_bases): return meta.__prepare__(name, bases) return type.__new__(metaclass, str('temporary_class'), (), {}) NoneType = type(None) primitive_types = (str, int, float, complex, bool, NoneType) def ensure_binary(value): try: return value.encode('utf-8') except AttributeError: # pragma: no cover # AttributeError: '<>' object has no attribute 'encode' # In this case assume already binary type and do nothing return value def ensure_text_type(value): try: return value.decode('utf-8') except AttributeError: # pragma: no cover # AttributeError: '<>' object has no attribute 'decode' # In this case assume already text_type and do nothing return value except UnicodeDecodeError: # pragma: no cover try: from chardet import detect except ImportError: try: from requests.packages.chardet import detect except ImportError: # pragma: no cover from pip._vendor.requests.packages.chardet import detect encoding = detect(value).get('encoding') or 'utf-8' return value.decode(encoding, errors='replace') except UnicodeEncodeError: # pragma: no cover # it's already str, so ignore? # not sure, surfaced with tests/models/test_match_spec.py test_tarball_match_specs # using py27 return value def ensure_unicode(value): try: return value.decode('unicode_escape') except AttributeError: # pragma: no cover # AttributeError: '<>' object has no attribute 'decode' # In this case assume already unicode and do nothing return value def ensure_fs_path_encoding(value): try: return value.encode(FILESYSTEM_ENCODING) except AttributeError: return value except UnicodeEncodeError: return value def ensure_utf8_encoding(value): try: return value.encode('utf-8') except AttributeError: return value except UnicodeEncodeError: return value