xref: /aosp_15_r20/external/autotest/client/common_lib/seven.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li# Copyright (c) 2020 The Chromium Authors. All rights reserved.
2*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be
3*9c5db199SXin Li# found in the LICENSE file.
4*9c5db199SXin Li"""Miscellaneous Python 2-3 compatibility functions.
5*9c5db199SXin Li
6*9c5db199SXin LiSeven is an extension to the compatibility layer six.
7*9c5db199SXin LiIt contains utilities that ease migration from Python 2
8*9c5db199SXin Lito Python 3, but aren't present in the six library.
9*9c5db199SXin Li"""
10*9c5db199SXin Li
11*9c5db199SXin Liimport six
12*9c5db199SXin Liimport six.moves.configparser
13*9c5db199SXin Liimport socket
14*9c5db199SXin Liimport sys
15*9c5db199SXin Liimport types
16*9c5db199SXin Li
17*9c5db199SXin Liif six.PY3:
18*9c5db199SXin Li    import builtins
19*9c5db199SXin Li    SOCKET_ERRORS = (builtins.ConnectionError, socket.timeout, socket.gaierror,
20*9c5db199SXin Li                     socket.herror)
21*9c5db199SXin Li    string_types = (str,)
22*9c5db199SXin Li    integer_types = (int,)
23*9c5db199SXin Li    class_types = (type,)
24*9c5db199SXin Li    text_type = str
25*9c5db199SXin Li    binary_type = bytes
26*9c5db199SXin Li
27*9c5db199SXin Li    MAXSIZE = sys.maxsize
28*9c5db199SXin Lielse:
29*9c5db199SXin Li    SOCKET_ERRORS = (socket.error, )
30*9c5db199SXin Li    string_types = (basestring,)
31*9c5db199SXin Li    integer_types = (int, long)
32*9c5db199SXin Li    class_types = (type, types.ClassType)
33*9c5db199SXin Li    text_type = unicode
34*9c5db199SXin Li    binary_type = str
35*9c5db199SXin Li
36*9c5db199SXin Li    MAXSIZE = float("inf")
37*9c5db199SXin Li
38*9c5db199SXin Li
39*9c5db199SXin Lidef exec_file(filename, globals_, locals_):
40*9c5db199SXin Li    """exec_file compiles and runs a file with globals and locals.
41*9c5db199SXin Li
42*9c5db199SXin Li    exec_file does not exactly mimic all the edge cases in Python 2's
43*9c5db199SXin Li    execfile function. Rather, it does only what is necessary to execute
44*9c5db199SXin Li    control files in autotest and prevent compiler-wide settings like
45*9c5db199SXin Li    'from __future__ import ...' from spilling into control files that
46*9c5db199SXin Li    have not yet been made Python 3-compatible.
47*9c5db199SXin Li
48*9c5db199SXin Li    Arguments:
49*9c5db199SXin Li        filename:   path to a file
50*9c5db199SXin Li        globals_:    dictionary of globals
51*9c5db199SXin Li        locals_:     dictionary of locals
52*9c5db199SXin Li
53*9c5db199SXin Li    Returns:
54*9c5db199SXin Li        None (output of six.exec_)
55*9c5db199SXin Li    """
56*9c5db199SXin Li    with open(filename, "rb") as fh:
57*9c5db199SXin Li        code_obj = compile(
58*9c5db199SXin Li                fh.read(),
59*9c5db199SXin Li                filename,
60*9c5db199SXin Li                mode="exec",
61*9c5db199SXin Li                flags=0,
62*9c5db199SXin Li                dont_inherit=1,
63*9c5db199SXin Li        )
64*9c5db199SXin Li    return six.exec_(code_obj, globals_, locals_)
65*9c5db199SXin Li
66*9c5db199SXin Li
67*9c5db199SXin Lidef config_parser(args=None):
68*9c5db199SXin Li    """config_parser returns a non-strict config parser.
69*9c5db199SXin Li
70*9c5db199SXin Li    Unfortunately, in six configparser is not same between 2/3. For our .ini's
71*9c5db199SXin Li    we do not want it to be strict (ie, error upon duplicates).
72*9c5db199SXin Li    """
73*9c5db199SXin Li    if six.PY3:
74*9c5db199SXin Li        return six.moves.configparser.ConfigParser(args, strict=False)
75*9c5db199SXin Li    return six.moves.configparser.ConfigParser(args)
76*9c5db199SXin Li
77*9c5db199SXin Li
78*9c5db199SXin Lidef ensure_text(s, encoding='utf-8', errors='strict'):
79*9c5db199SXin Li    """Coerce *s* to six.text_type. Copied from six lib.
80*9c5db199SXin Li
81*9c5db199SXin Li    For Python 2:
82*9c5db199SXin Li      - `unicode` -> `unicode`
83*9c5db199SXin Li      - `str` -> `unicode`
84*9c5db199SXin Li    For Python 3:
85*9c5db199SXin Li      - `str` -> `str`
86*9c5db199SXin Li      - `bytes` -> decoded to `str`
87*9c5db199SXin Li    """
88*9c5db199SXin Li    if isinstance(s, binary_type):
89*9c5db199SXin Li        return s.decode(encoding, errors)
90*9c5db199SXin Li    elif isinstance(s, text_type):
91*9c5db199SXin Li        return s
92*9c5db199SXin Li    else:
93*9c5db199SXin Li        raise TypeError("not expecting type '%s'" % type(s))
94*9c5db199SXin Li
95*9c5db199SXin Li
96*9c5db199SXin Lidef ensure_long(n):
97*9c5db199SXin Li    """ensure_long returns a long if py2, or int if py3."""
98*9c5db199SXin Li    if six.PY2:
99*9c5db199SXin Li        return long(n)
100*9c5db199SXin Li    return int(n)
101