Skip to content

Commit 2a6c25f

Browse files
Merge branch 'easybuilders:develop' into develop
2 parents 0571ab1 + 7ecec06 commit 2a6c25f

File tree

15 files changed

+145
-62
lines changed

15 files changed

+145
-62
lines changed

easybuild/_deprecated.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"""
3232
import contextlib
3333
import functools
34+
import json
3435
import os
3536
import re
3637
import signal
@@ -96,6 +97,12 @@ def cache_aware_func(cmd, *args, **kwargs):
9697
return cache_aware_func
9798

9899

100+
def json_loads(body):
101+
"""Deprecated wrapper for json.loads"""
102+
_log.deprecated("json_loads is deprecated, use json.loads", '6.0')
103+
return json.loads(body)
104+
105+
99106
def get_output_from_process(proc, read_size=None, asynchronous=False, print_deprecation_warning=True):
100107
"""
101108
Get output from running process (that was opened with subprocess.Popen).

easybuild/base/fancylogger.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -578,8 +578,7 @@ def logToFile(filename, enable=True, filehandler=None, name=None, max_bytes=MAX_
578578
'maxBytes': max_bytes,
579579
'backupCount': backup_count,
580580
}
581-
if sys.version_info[0] >= 3:
582-
handleropts['encoding'] = 'utf-8'
581+
handleropts['encoding'] = 'utf-8'
583582
# logging to a file is going to create the file later on, so let's try to be helpful and create the path if needed
584583
directory = os.path.dirname(filename)
585584
if not os.path.exists(directory):

easybuild/framework/easyblock.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@
9898
from easybuild.tools.filetools import is_sha256_checksum, mkdir, move_file, move_logs, read_file, remove_dir
9999
from easybuild.tools.filetools import remove_file, remove_lock, symlink, verify_checksum, weld_paths, write_file
100100
from easybuild.tools.hooks import (
101-
BUILD_STEP, CLEANUP_STEP, CONFIGURE_STEP, EXTENSIONS_STEP, EXTRACT_STEP, FETCH_STEP, INSTALL_STEP, MODULE_STEP,
102-
MODULE_WRITE, PACKAGE_STEP, PATCH_STEP, PERMISSIONS_STEP, POSTITER_STEP, POSTPROC_STEP, PREPARE_STEP, READY_STEP,
103-
SANITYCHECK_STEP, SINGLE_EXTENSION, TEST_STEP, TESTCASES_STEP, load_hooks, run_hook,
101+
BUILD_STEP, CLEANUP_STEP, CONFIGURE_STEP, EASYBLOCK, EXTENSIONS_STEP, EXTRACT_STEP, FETCH_STEP, INSTALL_STEP,
102+
MODULE_STEP, MODULE_WRITE, PACKAGE_STEP, PATCH_STEP, PERMISSIONS_STEP, POSTITER_STEP, POSTPROC_STEP, PREPARE_STEP,
103+
READY_STEP, SANITYCHECK_STEP, SINGLE_EXTENSION, TEST_STEP, TESTCASES_STEP, load_hooks, run_hook,
104104
)
105105
from easybuild.tools.run import RunShellCmdError, raise_run_shell_cmd_error, run_shell_cmd
106106
from easybuild.tools.jenkins import write_to_xml
@@ -448,7 +448,7 @@ def get_checksum_for(self, checksums, filename=None, index=None):
448448
if checksum and chksum_input_git is not None:
449449
# ignore any checksum for given filename due to changes in https://github.com/python/cpython/issues/90021
450450
# tarballs made for git repos are not reproducible when created with Python < 3.9
451-
if sys.version_info[0] >= 3 and sys.version_info[1] < 9:
451+
if sys.version_info < (3, 9):
452452
print_warning(
453453
"Reproducible tarballs of Git repos are only possible when using Python 3.9+ to run EasyBuild. "
454454
f"Skipping checksum verification of {chksum_input} since Python < 3.9 is used."
@@ -2830,8 +2830,6 @@ def patch_step(self, beginpath=None, patches=None):
28302830
self.log.info("Applying patch %s" % patch['name'])
28312831
trace_msg("applying patch %s" % patch['name'])
28322832

2833-
# patch source at specified index (first source if not specified)
2834-
srcind = patch.get('source', 0)
28352833
# if patch level is specified, use that (otherwise let apply_patch derive patch level)
28362834
level = patch.get('level', None)
28372835
# determine suffix of source path to apply patch in (if any)
@@ -2840,16 +2838,14 @@ def patch_step(self, beginpath=None, patches=None):
28402838
copy_patch = 'copy' in patch and 'sourcepath' not in patch
28412839
options = patch.get('opts', None) # Extra options for patch command
28422840

2843-
self.log.debug("Source index: %s; patch level: %s; source path suffix: %s; copy patch: %s; options: %s",
2844-
srcind, level, srcpathsuffix, copy_patch, options)
2841+
self.log.debug("Patch level: %s; source path suffix: %s; copy patch: %s; options: %s",
2842+
level, srcpathsuffix, copy_patch, options)
28452843

28462844
if beginpath is None:
2847-
try:
2848-
beginpath = self.src[srcind]['finalpath']
2849-
self.log.debug("Determine begin path for patch %s: %s" % (patch['name'], beginpath))
2850-
except IndexError as err:
2851-
raise EasyBuildError("Can't apply patch %s to source at index %s of list %s: %s",
2852-
patch['name'], srcind, self.src, err)
2845+
if not self.src:
2846+
raise EasyBuildError("Can't apply patch %s to source if no sources are given", patch['name'])
2847+
beginpath = self.src[0]['finalpath']
2848+
self.log.debug("Determined begin path for patch %s: %s" % (patch['name'], beginpath))
28532849
else:
28542850
self.log.debug("Using specified begin path for patch %s: %s" % (patch['name'], beginpath))
28552851

@@ -4662,18 +4658,19 @@ def run_step(self, step, step_methods):
46624658
run_hook(step, self.hooks, pre_step_hook=True, args=[self])
46634659

46644660
for step_method in step_methods:
4661+
# step_method is a lambda function that takes an EasyBlock instance as an argument,
4662+
# and returns the actual method
4663+
current_method = step_method(self)
46654664
# Remove leading underscore from e.g. "_test_step"
4666-
method_name = '_'.join(step_method.__code__.co_names).lstrip('_')
4665+
method_name = current_method.__name__.lstrip('_')
46674666
self.log.info("Running method %s part of step %s", method_name, step)
46684667

46694668
if self.dry_run:
46704669
self.dry_run_msg("[%s method]", method_name)
46714670

46724671
# if an known possible error occurs, just report it and continue
46734672
try:
4674-
# step_method is a lambda function that takes an EasyBlock instance as an argument,
4675-
# and returns the actual method, so use () to execute it
4676-
step_method(self)()
4673+
current_method()
46774674
except Exception as err:
46784675
if build_option('extended_dry_run_ignore_errors'):
46794676
dry_run_warning("ignoring error %s" % err, silent=self.silent)
@@ -4682,9 +4679,7 @@ def run_step(self, step, step_methods):
46824679
raise
46834680
self.dry_run_msg('')
46844681
else:
4685-
# step_method is a lambda function that takes an EasyBlock instance as an argument,
4686-
# and returns the actual method, so use () to execute it
4687-
step_method(self)()
4682+
current_method()
46884683

46894684
run_hook(step, self.hooks, post_step_hook=True, args=[self])
46904685

@@ -5001,6 +4996,8 @@ def build_and_install_one(ecdict, init_env):
50014996
_log.debug("Skip set to %s" % skip)
50024997
app.cfg['skip'] = skip
50034998

4999+
hooks = load_hooks(build_option('hooks'))
5000+
50045001
# build easyconfig
50055002
error_msg = '(no error)'
50065003
exit_code = None
@@ -5022,6 +5019,8 @@ def build_and_install_one(ecdict, init_env):
50225019
else:
50235020
enabled_write_permissions = False
50245021

5022+
run_hook(EASYBLOCK, hooks, pre_step_hook=True, args=[app])
5023+
50255024
result = app.run_all_steps(run_test_cases=run_test_cases)
50265025

50275026
if not dry_run:
@@ -5127,6 +5126,8 @@ def ensure_writable_log_dir(log_dir):
51275126
except EasyBuildError as err:
51285127
_log.warning("Unable to commit easyconfig to repository: %s", err)
51295128

5129+
run_hook(EASYBLOCK, hooks, post_step_hook=True, args=[app])
5130+
51305131
# cleanup logs
51315132
app.close_log()
51325133

easybuild/scripts/findPythonDeps.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@ def can_run(cmd, *arguments):
8585
def run_shell_cmd(arguments, action_desc, capture_stderr=True, **kwargs):
8686
"""Run the command and return the return code and output"""
8787
extra_args = kwargs or {}
88-
if sys.version_info[0] >= 3:
89-
extra_args['universal_newlines'] = True
88+
extra_args['universal_newlines'] = True
9089
stderr = subprocess.STDOUT if capture_stderr else subprocess.PIPE
9190
p = subprocess.Popen(arguments, stdout=subprocess.PIPE, stderr=stderr, **extra_args)
9291
out, err = p.communicate()

easybuild/tools/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ def mk_full_default_path(name, prefix=DEFAULT_PREFIX):
376376
EMPTY_LIST: [
377377
'accept_eula_for',
378378
'from_pr',
379+
'ignore_pip_unversioned_pkgs',
379380
'include_easyblocks_from_pr',
380381
'robot',
381382
'search_paths',

easybuild/tools/filetools.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def _hashlib_md5():
137137
to set usedforsecurity to False when supported (Python >= 3.9)
138138
"""
139139
kwargs = {}
140-
if sys.version_info[0] >= 3 and sys.version_info[1] >= 9:
140+
if sys.version_info >= (3, 9):
141141
kwargs = {'usedforsecurity': False}
142142
return hashlib.md5(**kwargs)
143143

@@ -219,10 +219,10 @@ def is_readable(path):
219219

220220

221221
def open_file(path, mode):
222-
"""Open a (usually) text file. If mode is not binary, then utf-8 encoding will be used for Python 3.x"""
222+
"""Open a (usually) text file. If mode is not binary, then utf-8 encoding will be used"""
223223
# This is required for text files in Python 3, especially until Python 3.7 which implements PEP 540.
224224
# This PEP opens files in UTF-8 mode if the C locale is used, see https://www.python.org/dev/peps/pep-0540
225-
if sys.version_info[0] >= 3 and 'b' not in mode:
225+
if 'b' not in mode:
226226
return open(path, mode, encoding='utf-8')
227227
else:
228228
return open(path, mode)
@@ -281,8 +281,8 @@ def write_file(path, data, append=False, forced=False, backup=False, always_over
281281

282282
data_is_file_obj = hasattr(data, 'read')
283283

284-
# special care must be taken with binary data in Python 3
285-
if sys.version_info[0] >= 3 and (isinstance(data, bytes) or data_is_file_obj):
284+
# special care must be taken with binary data
285+
if isinstance(data, bytes) or data_is_file_obj:
286286
mode += 'b'
287287

288288
# don't bother showing a progress bar for small files (< 10MB)
@@ -418,7 +418,7 @@ def remove(paths):
418418
_log.info("Removing %d files & directories", len(paths))
419419

420420
for path in paths:
421-
if os.path.isfile(path):
421+
if os.path.isfile(path) or os.path.islink(path):
422422
remove_file(path)
423423
elif os.path.isdir(path):
424424
remove_dir(path)

easybuild/tools/github.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import tempfile
4545
import time
4646
from datetime import datetime, timedelta
47+
from http.client import HTTPException
4748
from string import ascii_letters
4849
from urllib.request import HTTPError, URLError, urlopen
4950

@@ -281,7 +282,7 @@ def github_api_get_request(request_f, github_user=None, token=None, **kwargs):
281282

282283
try:
283284
status, data = url.get(**kwargs)
284-
except socket.gaierror as err:
285+
except (socket.gaierror, HTTPException) as err:
285286
_log.warning("Error occurred while performing get request: %s", err)
286287
status, data = 0, None
287288

easybuild/tools/hooks.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
START = 'start'
6363
PARSE = 'parse'
6464
BUILD_AND_INSTALL_LOOP = 'build_and_install_loop'
65+
EASYBLOCK = 'easyblock'
6566
SINGLE_EXTENSION = 'single_extension'
6667
MODULE_WRITE = 'module_write'
6768
END = 'end'
@@ -86,6 +87,7 @@
8687
START,
8788
PARSE,
8889
PRE_PREF + BUILD_AND_INSTALL_LOOP,
90+
PRE_PREF + EASYBLOCK,
8991
] + [p + x for x in STEP_NAMES[:STEP_NAMES.index(EXTENSIONS_STEP)]
9092
for p in [PRE_PREF, POST_PREF]] + [
9193
# pre-extensions hook is triggered before starting installation of extensions,
@@ -105,6 +107,7 @@
105107
POST_PREF + MODULE_STEP,
106108
] + [p + x for x in STEP_NAMES[STEP_NAMES.index(MODULE_STEP)+1:]
107109
for p in [PRE_PREF, POST_PREF]] + [
110+
POST_PREF + EASYBLOCK,
108111
POST_PREF + BUILD_AND_INSTALL_LOOP,
109112
END,
110113
CANCEL,

easybuild/tools/options.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,8 @@ def override_options(self):
498498
'ignore-checksums': ("Ignore failing checksum verification", None, 'store_true', False),
499499
'ignore-test-failure': ("Ignore a failing test step", None, 'store_true', False),
500500
'ignore-osdeps': ("Ignore any listed OS dependencies", None, 'store_true', False),
501+
'ignore-pip-unversioned-pkgs': ("List of installed unversioned (0.0.0) python packages to ignore in the "
502+
"sanity check", 'strlist', 'store', []),
501503
'insecure-download': ("Don't check the server certificate against the available certificate authorities.",
502504
None, 'store_true', False),
503505
'install-latest-eb-release': ("Install latest known version of easybuild", None, 'store_true', False),

easybuild/tools/py2vs3/py3.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@
3333
"""
3434
# these are not used here, but imported from here in other places
3535
import configparser # noqa
36-
import json
37-
import sys
3836
import urllib.request as std_urllib # noqa
3937
from collections.abc import Mapping # noqa
4038
from functools import cmp_to_key
@@ -59,6 +57,7 @@
5957
except ImportError:
6058
HAVE_DISTUTILS = False
6159

60+
from easybuild._deprecated import json_loads # noqa
6261
from easybuild.base.wrapper import mk_wrapper_baseclass # noqa
6362
from easybuild.tools.run import subprocess_popen_text, subprocess_terminate # noqa
6463

@@ -75,18 +74,6 @@ def load_source(filename, path):
7574
return module
7675

7776

78-
def json_loads(body):
79-
"""Wrapper for json.loads that takes into account that Python versions older than 3.6 require a string value."""
80-
81-
if isinstance(body, bytes) and sys.version_info[0] == 3 and sys.version_info[1] < 6:
82-
# decode bytes string as regular string with UTF-8 encoding for Python 3.5.x and older
83-
# only Python 3.6 and newer have support for passing bytes string to json.loads
84-
# cfr. https://docs.python.org/2/library/json.html#json.loads
85-
body = body.decode('utf-8', 'ignore')
86-
87-
return json.loads(body)
88-
89-
9077
def raise_with_traceback(exception_class, message, traceback):
9178
"""Raise exception of specified class with given message and traceback."""
9279
raise exception_class(message).with_traceback(traceback)

0 commit comments

Comments
 (0)