From 53288e24f370c2723bd744948a8f25b3ffa33b14 Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Thu, 5 Oct 2023 12:35:26 +0100 Subject: [PATCH 1/3] setup.py: Remove use of "imp" module Python 3.12 removed the "imp" module, so replace its use in devlib. --- setup.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index bf1b408ff..089eb9216 100644 --- a/setup.py +++ b/setup.py @@ -13,11 +13,11 @@ # limitations under the License. # -import imp import os import sys import warnings from itertools import chain +import types try: from setuptools import setup @@ -35,15 +35,25 @@ warnings.filterwarnings('ignore', "Unknown distribution option: 'install_requires'") warnings.filterwarnings('ignore', "Unknown distribution option: 'extras_require'") + try: os.remove('MANIFEST') except OSError: pass +def _load_path(filepath): + # Not a proper import in many, many ways but does the job for really basic + # needs + with open(filepath) as f: + globals_ = dict(__file__=filepath) + exec(f.read(), globals_) + return types.SimpleNamespace(**globals_) + + vh_path = os.path.join(devlib_dir, 'utils', 'version.py') # can load this, as it does not have any devlib imports -version_helper = imp.load_source('version_helper', vh_path) +version_helper = _load_path(vh_path) __version__ = version_helper.get_devlib_version() commit = version_helper.get_commit() if commit: From 157c15ede76c642c77150fc9434ac00834853995 Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Thu, 5 Oct 2023 13:19:10 +0100 Subject: [PATCH 2/3] devlib: Remove Python 2 dead code Remove code that was used for Python 2 only. --- devlib/collector/ftrace.py | 3 +- devlib/instrument/acmecape.py | 5 +--- devlib/instrument/energy_probe.py | 5 ++-- devlib/instrument/monsoon.py | 5 ++-- devlib/target.py | 5 +--- devlib/utils/android.py | 3 +- devlib/utils/csvutil.py | 20 +++---------- devlib/utils/misc.py | 6 +--- devlib/utils/rendering.py | 5 +--- devlib/utils/ssh.py | 11 ++----- devlib/utils/types.py | 48 ++++++++++++------------------- devlib/utils/version.py | 2 +- 12 files changed, 36 insertions(+), 82 deletions(-) diff --git a/devlib/collector/ftrace.py b/devlib/collector/ftrace.py index 057d7322e..d35615401 100644 --- a/devlib/collector/ftrace.py +++ b/devlib/collector/ftrace.py @@ -408,8 +408,7 @@ def report(self, binfile, destfile): self.logger.debug(command) process = subprocess.Popen(command, stderr=subprocess.PIPE, shell=True) _, error = process.communicate() - if sys.version_info[0] == 3: - error = error.decode(sys.stdout.encoding or 'utf-8', 'replace') + error = error.decode(sys.stdout.encoding or 'utf-8', 'replace') if process.returncode: raise TargetStableError('trace-cmd returned non-zero exit code {}'.format(process.returncode)) if error: diff --git a/devlib/instrument/acmecape.py b/devlib/instrument/acmecape.py index ec0a77bf6..cfbcbe071 100644 --- a/devlib/instrument/acmecape.py +++ b/devlib/instrument/acmecape.py @@ -116,10 +116,7 @@ def stop(self): msg = 'Could not terminate iio-capture:\n{}' raise HostError(msg.format(output)) if self.process.returncode != 15: # iio-capture exits with 15 when killed - if sys.version_info[0] == 3: - output += self.process.stdout.read().decode(sys.stdout.encoding or 'utf-8', 'replace') - else: - output += self.process.stdout.read() + output += self.process.stdout.read().decode(sys.stdout.encoding or 'utf-8', 'replace') self.logger.info('ACME instrument encountered an error, ' 'you may want to try rebooting the ACME device:\n' ' ssh root@{} reboot'.format(self.host)) diff --git a/devlib/instrument/energy_probe.py b/devlib/instrument/energy_probe.py index b0b51801a..6a97c5bf2 100644 --- a/devlib/instrument/energy_probe.py +++ b/devlib/instrument/energy_probe.py @@ -86,9 +86,8 @@ def stop(self): self.process.poll() if self.process.returncode is not None: stdout, stderr = self.process.communicate() - if sys.version_info[0] == 3: - stdout = stdout.decode(sys.stdout.encoding or 'utf-8', 'replace') - stderr = stderr.decode(sys.stdout.encoding or 'utf-8', 'replace') + stdout = stdout.decode(sys.stdout.encoding or 'utf-8', 'replace') + stderr = stderr.decode(sys.stdout.encoding or 'utf-8', 'replace') raise HostError( 'Energy Probe: Caiman exited unexpectedly with exit code {}.\n' 'stdout:\n{}\nstderr:\n{}'.format(self.process.returncode, diff --git a/devlib/instrument/monsoon.py b/devlib/instrument/monsoon.py index ac1741dbe..97999177b 100644 --- a/devlib/instrument/monsoon.py +++ b/devlib/instrument/monsoon.py @@ -100,9 +100,8 @@ def stop(self): process.poll() if process.returncode is not None: stdout, stderr = process.communicate() - if sys.version_info[0] == 3: - stdout = stdout.encode(sys.stdout.encoding or 'utf-8') - stderr = stderr.encode(sys.stdout.encoding or 'utf-8') + stdout = stdout.encode(sys.stdout.encoding or 'utf-8') + stderr = stderr.encode(sys.stdout.encoding or 'utf-8') raise HostError( 'Monsoon script exited unexpectedly with exit code {}.\n' 'stdout:\n{}\nstderr:\n{}'.format(process.returncode, diff --git a/devlib/target.py b/devlib/target.py index f4c5ebd78..337bc0f42 100644 --- a/devlib/target.py +++ b/devlib/target.py @@ -2018,10 +2018,7 @@ async def capture_ui_hierarchy(self, filepath): parsed_xml = xml.dom.minidom.parse(filepath) with open(filepath, 'w') as f: - if sys.version_info[0] == 3: - f.write(parsed_xml.toprettyxml()) - else: - f.write(parsed_xml.toprettyxml().encode('utf-8')) + f.write(parsed_xml.toprettyxml()) @asyn.asyncf async def is_installed(self, name): diff --git a/devlib/utils/android.py b/devlib/utils/android.py index 0b4b07452..753094b53 100755 --- a/devlib/utils/android.py +++ b/devlib/utils/android.py @@ -243,8 +243,7 @@ def _run(self, command): logger.debug(' '.join(command)) try: output = subprocess.check_output(command, stderr=subprocess.STDOUT) - if sys.version_info[0] == 3: - output = output.decode(sys.stdout.encoding or 'utf-8', 'replace') + output = output.decode(sys.stdout.encoding or 'utf-8', 'replace') except subprocess.CalledProcessError as e: raise HostError('Error while running "{}":\n{}' .format(command, e.output)) diff --git a/devlib/utils/csvutil.py b/devlib/utils/csvutil.py index 2cb1212f9..b696449fa 100644 --- a/devlib/utils/csvutil.py +++ b/devlib/utils/csvutil.py @@ -60,10 +60,7 @@ @contextmanager def csvwriter(filepath, *args, **kwargs): - if sys.version_info[0] == 3: - wfh = open(filepath, 'w', newline='') - else: - wfh = open(filepath, 'wb') + wfh = open(filepath, 'w', newline='') try: yield csv.writer(wfh, *args, **kwargs) @@ -73,10 +70,7 @@ def csvwriter(filepath, *args, **kwargs): @contextmanager def csvreader(filepath, *args, **kwargs): - if sys.version_info[0] == 3: - fh = open(filepath, 'r', newline='') - else: - fh = open(filepath, 'rb') + fh = open(filepath, 'r', newline='') try: yield csv.reader(fh, *args, **kwargs) @@ -85,16 +79,10 @@ def csvreader(filepath, *args, **kwargs): def create_writer(filepath, *args, **kwargs): - if sys.version_info[0] == 3: - wfh = open(filepath, 'w', newline='') - else: - wfh = open(filepath, 'wb') + wfh = open(filepath, 'w', newline='') return csv.writer(wfh, *args, **kwargs), wfh def create_reader(filepath, *args, **kwargs): - if sys.version_info[0] == 3: - fh = open(filepath, 'r', newline='') - else: - fh = open(filepath, 'rb') + fh = open(filepath, 'r', newline='') return csv.reader(fh, *args, **kwargs), fh diff --git a/devlib/utils/misc.py b/devlib/utils/misc.py index 47348927f..58cf6eca1 100644 --- a/devlib/utils/misc.py +++ b/devlib/utils/misc.py @@ -594,11 +594,7 @@ def __str__(self): RAND_MOD_NAME_LEN = 30 BAD_CHARS = string.punctuation + string.whitespace -# pylint: disable=no-member -if sys.version_info[0] == 3: - TRANS_TABLE = str.maketrans(BAD_CHARS, '_' * len(BAD_CHARS)) -else: - TRANS_TABLE = string.maketrans(BAD_CHARS, '_' * len(BAD_CHARS)) +TRANS_TABLE = str.maketrans(BAD_CHARS, '_' * len(BAD_CHARS)) def to_identifier(text): diff --git a/devlib/utils/rendering.py b/devlib/utils/rendering.py index 3df82d61c..52d4f00dc 100644 --- a/devlib/utils/rendering.py +++ b/devlib/utils/rendering.py @@ -217,10 +217,7 @@ def __init__(self, target, period, package, header=None): def collect_frames(self, wfh): cmd = 'dumpsys gfxinfo {} framestats' result = self.target.execute(cmd.format(self.package)) - if sys.version_info[0] == 3: - wfh.write(result.encode('utf-8')) - else: - wfh.write(result) + wfh.write(result.encode('utf-8')) def clear(self): pass diff --git a/devlib/utils/ssh.py b/devlib/utils/ssh.py index 0feceaf66..c985ed2c8 100644 --- a/devlib/utils/ssh.py +++ b/devlib/utils/ssh.py @@ -758,11 +758,7 @@ def callback(output_chunks, name, chunk): output_chunks, exit_code = _read_paramiko_streams(stdout, stderr, select_timeout, callback, []) # Join in one go to avoid O(N^2) concatenation output = b''.join(output_chunks) - - if sys.version_info[0] == 3: - output = output.decode(sys.stdout.encoding or 'utf-8', 'replace') - if strip_colors: - output = strip_bash_colors(output) + output = output.decode(sys.stdout.encoding or 'utf-8', 'replace') return (exit_code, output) @@ -970,10 +966,7 @@ def _execute_and_wait_for_prompt(self, command, timeout=None, as_root=False, str logger.debug(command) self._sendline(command) timed_out = self._wait_for_prompt(timeout) - if sys.version_info[0] == 3: - output = process_backspaces(self.conn.before.decode(sys.stdout.encoding or 'utf-8', 'replace')) - else: - output = process_backspaces(self.conn.before) + output = process_backspaces(self.conn.before.decode(sys.stdout.encoding or 'utf-8', 'replace')) if timed_out: self.cancel_running_command() diff --git a/devlib/utils/types.py b/devlib/utils/types.py index f212930e2..d7c8864b0 100644 --- a/devlib/utils/types.py +++ b/devlib/utils/types.py @@ -136,35 +136,25 @@ def bitmask(value): regex_type = type(re.compile('')) -if sys.version_info[0] == 3: - def regex(value): - if isinstance(value, regex_type): - if isinstance(value.pattern, str): - return value - return re.compile(value.pattern.decode(), - value.flags | re.UNICODE) - else: - if isinstance(value, bytes): - value = value.decode() - return re.compile(value) - - - def bytes_regex(value): - if isinstance(value, regex_type): - if isinstance(value.pattern, bytes): - return value - return re.compile(value.pattern.encode(sys.stdout.encoding or 'utf-8'), - value.flags & ~re.UNICODE) - else: - if isinstance(value, str): - value = value.encode(sys.stdout.encoding or 'utf-8') - return re.compile(value) -else: - def regex(value): - if isinstance(value, regex_type): +def regex(value): + if isinstance(value, regex_type): + if isinstance(value.pattern, str): return value - else: - return re.compile(value) + return re.compile(value.pattern.decode(), + value.flags | re.UNICODE) + else: + if isinstance(value, bytes): + value = value.decode() + return re.compile(value) - bytes_regex = regex +def bytes_regex(value): + if isinstance(value, regex_type): + if isinstance(value.pattern, bytes): + return value + return re.compile(value.pattern.encode(sys.stdout.encoding or 'utf-8'), + value.flags & ~re.UNICODE) + else: + if isinstance(value, str): + value = value.encode(sys.stdout.encoding or 'utf-8') + return re.compile(value) diff --git a/devlib/utils/version.py b/devlib/utils/version.py index a44498b65..ec6a3f1c5 100644 --- a/devlib/utils/version.py +++ b/devlib/utils/version.py @@ -42,7 +42,7 @@ def get_commit(): p.wait() if p.returncode: return None - if sys.version_info[0] == 3 and isinstance(std, bytes): + if isinstance(std, bytes): return std[:8].decode(sys.stdout.encoding or 'utf-8', 'replace') else: return std[:8] From c4ebee7feb3647a7c476a26e2245dc0783f4e2c8 Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Thu, 5 Oct 2023 13:31:45 +0100 Subject: [PATCH 3/3] setup.py: Re-add "future" PyPI package Re-add the "future" PyPI package since it actually contains the "past" Python package that devlib still uses. --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 089eb9216..06b20952c 100644 --- a/setup.py +++ b/setup.py @@ -104,6 +104,7 @@ def _load_path(filepath): 'pandas', 'lxml', # More robust xml parsing 'nest_asyncio', # Allows running nested asyncio loops + 'future', # for the "past" Python package ], extras_require={ 'daq': ['daqpower>=2'],