# Copyright (c) 2020 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Miscellaneous Python 2-3 compatibility functions. Seven is an extension to the compatibility layer six. It contains utilities that ease migration from Python 2 to Python 3, but aren't present in the six library. """ import six import six.moves.configparser import socket import sys import types if six.PY3: import builtins SOCKET_ERRORS = (builtins.ConnectionError, socket.timeout, socket.gaierror, socket.herror) string_types = (str,) integer_types = (int,) class_types = (type,) text_type = str binary_type = bytes MAXSIZE = sys.maxsize else: SOCKET_ERRORS = (socket.error, ) string_types = (basestring,) integer_types = (int, long) class_types = (type, types.ClassType) text_type = unicode binary_type = str MAXSIZE = float("inf") def exec_file(filename, globals_, locals_): """exec_file compiles and runs a file with globals and locals. exec_file does not exactly mimic all the edge cases in Python 2's execfile function. Rather, it does only what is necessary to execute control files in autotest and prevent compiler-wide settings like 'from __future__ import ...' from spilling into control files that have not yet been made Python 3-compatible. Arguments: filename: path to a file globals_: dictionary of globals locals_: dictionary of locals Returns: None (output of six.exec_) """ with open(filename, "rb") as fh: code_obj = compile( fh.read(), filename, mode="exec", flags=0, dont_inherit=1, ) return six.exec_(code_obj, globals_, locals_) def config_parser(): """config_parser returns a non-strict config parser. Unfortunately, in six configparser is not same between 2/3. For our .ini's we do not want it to be strict (ie, error upon duplicates). """ if six.PY3: return six.moves.configparser.ConfigParser(strict=False) return six.moves.configparser.ConfigParser() def ensure_text(s, encoding='utf-8', errors='strict'): """Coerce *s* to six.text_type. Copied from six lib. For Python 2: - `unicode` -> `unicode` - `str` -> `unicode` For Python 3: - `str` -> `str` - `bytes` -> decoded to `str` """ if isinstance(s, binary_type): return s.decode(encoding, errors) elif isinstance(s, text_type): return s else: raise TypeError("not expecting type '%s'" % type(s)) def ensure_long(n): """ensure_long returns a long if py2, or int if py3.""" if six.PY2: return long(n) return int(n)