diff --git a/build_scripts/build_runner.py b/build_scripts/build_runner.py index e3e3336a..6e306f1a 100644 --- a/build_scripts/build_runner.py +++ b/build_scripts/build_runner.py @@ -43,7 +43,8 @@ import logging from collections import OrderedDict from copy import deepcopy -from datetime import datetime + +import dateutil.parser from tenacity import retry, stop_after_attempt, wait_exponential sys.path.append(str(pathlib.Path(__file__).resolve().parents[1])) @@ -243,7 +244,7 @@ def __init__(self, build_config_path, root_dir, build_type, product_type, build_ :type stage: String :param commit_time: Time for getting slice of commits of repositories - :type commit_time: datetime + :type commit_time: String :param changed_repo: Information about changed source repository :type changed_repo: String @@ -260,13 +261,13 @@ def __init__(self, build_config_path, root_dir, build_type, product_type, build_ """ self._default_stage = Stage.BUILD.value - super().__init__(root_dir, build_config_path, stage) + super().__init__(root_dir, build_config_path, stage, custom_cli_args) self._product_repos = {} self._product = None self._product_type = product_type self._build_event = build_event - self._commit_time = commit_time + self._commit_time = dateutil.parser.parse(commit_time) if commit_time else None self._changed_repo = changed_repo self._repo_states = None self._build_state_file = root_dir / "build_state" @@ -281,7 +282,6 @@ def __init__(self, build_config_path, root_dir, build_type, product_type, build_ }) self._dev_pkg_data_to_archive = [] self._install_pkg_data_to_archive = [] - self._custom_cli_args = custom_cli_args self._target_arch = target_arch self._target_branch = target_branch self._manifest_file = manifest_file @@ -326,7 +326,6 @@ def _update_global_vars(self): 'vs_component': self._vs_component, 'stage': Stage, 'copy_win_files': copy_win_files, - 'args': self._custom_cli_args, 'product_type': self._product_type, 'build_event': self._build_event, # TODO should be in lower case @@ -1013,7 +1012,7 @@ def main(): choices=[stage.value for stage in Stage], help="Current executable stage") parser.add_argument('-t', "--commit-time", metavar='datetime', - help="Time of commits (ex. 2017-11-02 07:36:40)") + help="Time of commits (e.g. 2017-11-02 07:36:40)") parser.add_argument('-ta', "--target-arch", nargs='*', default=[target_arch.value for target_arch in TargetArch], @@ -1022,15 +1021,15 @@ def main(): parser.add_argument('-tb', "--target-branch", help=f'All not triggered repos will be checkout to this branch.') - parsed_args, unknown_args = parser.parse_known_args() + args, unknown_args = parser.parse_known_args() configure_logger() - if parsed_args.stage != Stage.CLEAN.value: - configure_logger(logs_path=pathlib.Path(parsed_args.root_dir) / 'logs' / f'{parsed_args.stage}.log') + if args.stage != Stage.CLEAN.value: + configure_logger(logs_path=pathlib.Path(args.root_dir) / 'logs' / f'{args.stage}.log') log = logging.getLogger('build_runner.main') # remove duplicated values - target_arch = list(set(parsed_args.target_arch)) + target_arch = list(set(args.target_arch)) custom_cli_args = {} if unknown_args: @@ -1042,40 +1041,35 @@ def main(): log.exception(f'Wrong argument layout: {arg}') exit(ErrorCode.CRITICAL) - if parsed_args.commit_time: - commit_time = datetime.strptime(parsed_args.commit_time, '%Y-%m-%d %H:%M:%S') - else: - commit_time = None - try: build_config = BuildGenerator( - build_config_path=pathlib.Path(parsed_args.build_config).absolute(), - root_dir=pathlib.Path(parsed_args.root_dir).absolute(), - build_type=parsed_args.build_type, - product_type=parsed_args.product_type, - build_event=parsed_args.build_event, - commit_time=commit_time, - changed_repo=parsed_args.changed_repo, - repo_states_file_path=parsed_args.repo_states, + build_config_path=pathlib.Path(args.build_config).absolute(), + root_dir=pathlib.Path(args.root_dir).absolute(), + build_type=args.build_type, + product_type=args.product_type, + build_event=args.build_event, + commit_time=args.commit_time, + changed_repo=args.changed_repo, + repo_states_file_path=args.repo_states, custom_cli_args=custom_cli_args, - stage=parsed_args.stage, + stage=args.stage, target_arch=target_arch, - target_branch=parsed_args.target_branch, - manifest_file=parsed_args.manifest, - component_name=parsed_args.component + target_branch=args.target_branch, + manifest_file=args.manifest, + component_name=args.component ) - if not parsed_args.changed_repo \ - and not parsed_args.repo_states \ - and (not parsed_args.manifest or not parsed_args.component): + if not args.changed_repo \ + and not args.repo_states \ + and (not args.manifest or not args.component): log.warning('"--changed-repo" or "--repo-states" or "--manifest" and "--component" ' 'arguments are not set, "HEAD" revision and "master" branch will be used') - elif parsed_args.changed_repo and parsed_args.repo_states: + elif args.changed_repo and args.repo_states: log.warning('The --repo-states argument is ignored because the --changed-repo is set') # prepare build configuration if build_config.generate_config(): - no_errors = build_config.run_stage(parsed_args.stage) + no_errors = build_config.run_stage(args.stage) else: no_errors = False @@ -1083,16 +1077,16 @@ def main(): no_errors = False log.exception('Exception occurred') - build_state_file = pathlib.Path(parsed_args.root_dir) / 'build_state' + build_state_file = pathlib.Path(args.root_dir) / 'build_state' if no_errors: if not build_state_file.exists(): build_state_file.write_text(json.dumps({'status': "PASS"})) log.info('-' * 50) - log.info("%s STAGE COMPLETED", parsed_args.stage.upper()) + log.info("%s STAGE COMPLETED", args.stage.upper()) else: build_state_file.write_text(json.dumps({'status': "FAIL"})) log.error('-' * 50) - log.error("%s STAGE FAILED", parsed_args.stage.upper()) + log.error("%s STAGE FAILED", args.stage.upper()) exit(ErrorCode.CRITICAL.value) diff --git a/build_scripts/common_runner.py b/build_scripts/common_runner.py index 3d01501f..320f8fbf 100644 --- a/build_scripts/common_runner.py +++ b/build_scripts/common_runner.py @@ -177,9 +177,11 @@ def _parse_logs(self, stdout): class ConfigGenerator: _default_stage = None - def __init__(self, root_dir, config_path, current_stage): + def __init__(self, root_dir, config_path, current_stage, custom_cli_args=None): self._config_path = config_path self._current_stage = current_stage + self._custom_cli_args = custom_cli_args or {} + self._actions = defaultdict(list) self._options = { "ROOT_DIR": pathlib.Path(root_dir).absolute(), @@ -193,9 +195,12 @@ def __init__(self, root_dir, config_path, current_stage): self._config_variables = {} self._global_vars = { - 'action': self._action, 'options': self._options, - 'log': self._log + 'args': self._custom_cli_args, + 'log': self._log, + 'configs_dir': self._config_path.parent, + 'infra_dir': pathlib.Path(__file__).resolve().parents[1], + 'action': self._action, } if not self._default_stage: diff --git a/build_scripts/tests_runner.py b/build_scripts/tests_runner.py index 739b764a..76ffcaba 100644 --- a/build_scripts/tests_runner.py +++ b/build_scripts/tests_runner.py @@ -30,6 +30,8 @@ import pathlib import argparse +import dateutil.parser + sys.path.append(str(pathlib.Path(__file__).resolve().parents[1])) from build_scripts.common_runner import ConfigGenerator, RunnerException from test_scripts.components_installer import install_components @@ -60,10 +62,11 @@ class TestRunner(ConfigGenerator): Contains commands for testing product. """ - def __init__(self, artifacts, root_dir, current_stage): + def __init__(self, artifacts, root_dir, current_stage, commit_time=None, custom_cli_args=None): self._artifacts_dir = None self._manifest = None self._infrastructure_path = pathlib.Path(__file__).resolve().parents[1] + self._commit_time = dateutil.parser.parse(commit_time) if commit_time else None if artifacts.exists(): if artifacts.is_file(): @@ -85,13 +88,15 @@ def __init__(self, artifacts, root_dir, current_stage): raise ArtifactsNotFoundException(f'"{artifacts}" does not exist') self._default_stage = TestStage.TEST.value - super().__init__(root_dir, config_path, current_stage) + super().__init__(root_dir, config_path, current_stage, custom_cli_args) def _update_global_vars(self): self._global_vars.update({ 'stage': TestStage, + # TODO: remove infra_path 'infra_path': self._infrastructure_path, 'artifacts_dir': self._artifacts_dir, + 'commit_time': self._commit_time, }) def _clean(self): @@ -166,17 +171,31 @@ def main(): parser.add_argument("--stage", default=TestStage.TEST.value, choices=[stage.value for stage in TestStage], help="Current executable stage") - args = parser.parse_args() + parser.add_argument('-t', "--commit-time", metavar='datetime', + help="Time of commits (e.g. 2017-11-02 07:36:40)") + args, unknown_args = parser.parse_known_args() configure_logger() if args.stage != TestStage.CLEAN.value: configure_logger(logs_path=pathlib.Path(args.root_dir) / 'logs' / f'{args.stage}.log') log = logging.getLogger('tests_runner.main') + custom_cli_args = {} + if unknown_args: + for arg in unknown_args: + try: + arg = arg.split('=') + custom_cli_args[arg[0]] = arg[1] + except Exception: + log.exception(f'Wrong argument layout: {arg}') + exit(ErrorCode.CRITICAL) + try: tests_runner = TestRunner(artifacts=pathlib.Path(args.artifacts).absolute(), root_dir=pathlib.Path(args.root_dir).absolute(), - current_stage=args.stage) + current_stage=args.stage, + commit_time=args.commit_time, + custom_cli_args=custom_cli_args) if tests_runner.generate_config(): no_errors = tests_runner.run_stage(args.stage) diff --git a/common/extract_repo.py b/common/extract_repo.py index 8ff2c770..7e3d6636 100644 --- a/common/extract_repo.py +++ b/common/extract_repo.py @@ -29,7 +29,6 @@ import shutil from distutils.dir_util import copy_tree from importlib import reload -from datetime import datetime sys.path.append(str(pathlib.Path(__file__).resolve().parents[1])) from common import git_worker @@ -74,12 +73,9 @@ def extract_repo(root_repo_dir, repo_name, branch, commit_id=None, commit_time=N f'Release branch {branch} does not exist in the repo {repo.repo_name}') # repo.branch = branch - repo.change_repo_state(branch_name=branch, - commit_time=datetime.strptime(commit_time, - '%Y-%m-%d %H:%M:%S').timestamp()) + repo.change_repo_state(branch_name=branch, commit_time=commit_time) else: - repo.change_repo_state( - commit_time=datetime.strptime(commit_time, '%Y-%m-%d %H:%M:%S').timestamp()) + repo.change_repo_state(commit_time=commit_time) else: log.info('Commit id and timestamp not specified, clone HEAD of repository') repo = git_worker.GitRepo(root_repo_dir=root_repo_dir, repo_name=repo_name, @@ -278,8 +274,8 @@ def main(): help='Branch name, by default "master" branch') parser.add_argument("--commit-id", metavar="String", help='SHA of commit') - parser.add_argument("--commit-time", metavar="String", - help='Will switch to the commit before specified time') + parser.add_argument("--commit-time", metavar="datetime", + help='Switch to a commit before the time (e.g. 2017-11-02 07:36:40)') args = parser.parse_args() configure_logger() diff --git a/common/git_worker.py b/common/git_worker.py index f2476d35..4f1da6a5 100644 --- a/common/git_worker.py +++ b/common/git_worker.py @@ -19,7 +19,11 @@ # SOFTWARE. """ -Module for working with Git +Module for working with Git using GitPython +Using environment variables, you can further adjust the behaviour of the git command. +GIT_PYTHON_TRACE + If set to non-0, all executed git commands will be shown as they happen + If set to full, the executed git command _and_ its entire output on stdout and stderr """ import collections import json @@ -30,10 +34,11 @@ from datetime import datetime import git +import dateutil.parser from tenacity import retry, stop_after_attempt, wait_exponential, \ retry_if_exception_type, retry_if_result -from common.helper import remove_directory +from common import helper from common.mediasdk_directories import MediaSdkDirectories, THIRD_PARTY @@ -84,10 +89,9 @@ def prepare_repo(self): :return: None """ self.log.info('-' * 50) - self.log.info("Getting repo: %s", self.repo_name) + self.log.info("Prepare repo: %s", self.repo_name) self.clone() - self.repo = git.Repo(str(self.local_repo_dir)) self.hard_reset() self.clean() self.checkout(branch_name="master", silent=True) @@ -106,14 +110,15 @@ def clone(self): # if dir is not repository, it will be removed if self.local_repo_dir.exists(): try: - git.Repo(str(self.local_repo_dir)) + self.repo = git.Repo(str(self.local_repo_dir)) except git.InvalidGitRepositoryError: - self.log.info('Remove broken repo %s', self.local_repo_dir) - remove_directory(self.local_repo_dir) + self.log.info('Remove broken repo: %s', self.local_repo_dir) + helper.remove_directory(self.local_repo_dir) if not self.local_repo_dir.exists(): - self.log.info("Clone repo " + self.repo_name) + self.log.info("Clone repo: %s", self.repo_name) git.Git().clone(self.url, str(self.local_repo_dir)) + self.repo = git.Repo(str(self.local_repo_dir)) @retry(stop=stop_after_attempt(5), wait=wait_exponential(multiplier=60)) def fetch(self, branch_name=None): @@ -124,7 +129,7 @@ def fetch(self, branch_name=None): """ refname = branch_name or self.branch_name - self.log.info("Fetch repo %s to %s", self.repo_name, refname) + self.log.info("Fetch repo '%s' to '%s'", self.repo_name, refname) self.repo.remotes.origin.fetch(refname) self.hard_reset('FETCH_HEAD') @@ -137,7 +142,7 @@ def hard_reset(self, reset_to="HEAD"): :return: None """ - self.log.info(f"Hard reset repo {self.repo_name} to {reset_to}") + self.log.info(f"Hard reset repo '{self.repo_name}' to '{reset_to}'") if reset_to: self.repo.git.reset('--hard', reset_to) else: @@ -160,7 +165,7 @@ def checkout(self, branch_name=None, silent=False): """ checkout_dest = branch_name or self.commit_id - self.log.info("Checkout repo %s to %s", self.repo_name, checkout_dest) + self.log.info("Checkout repo '%s' to '%s'", self.repo_name, checkout_dest) try: self.repo.git.checkout(checkout_dest, force=True) except git.exc.GitCommandError as err: @@ -185,7 +190,7 @@ def clean(self): :return: None """ - self.log.info("Clean repo " + self.repo_name) + self.log.info("Clean repo: %s", self.repo_name) self.repo.git.clean('-xdf') @retry(stop=stop_after_attempt(5), wait=wait_exponential(multiplier=60)) @@ -195,9 +200,13 @@ def pull(self): :return: None """ - self.log.info("Pull repo " + self.repo_name) + self.log.info("Pull repo: %s", self.repo_name) self.repo.git.pull() + for submodule in self.repo.submodules: + self.log.info(f"Update submodule: {submodule}") + submodule.update(init=True) + def change_repo_state(self, branch_name=None, commit_time=None): """ Change the repo state @@ -229,17 +238,24 @@ def revert_commit_by_time(self, commit_time): If commit date <= certain time, commit sets to class variable commit_id. - :param commit_time: timestamp + :param commit_time: Union[str, datetime, timestamp] :return: None """ + if isinstance(commit_time, str): + time_stamp = dateutil.parser.parse(commit_time).timestamp() + elif isinstance(commit_time, datetime): + time_stamp = commit_time.timestamp() + else: + time_stamp = commit_time + try: - self.commit_id = str(next(self.repo.iter_commits(until=commit_time, max_count=1))) + self.commit_id = str(next(self.repo.iter_commits(until=time_stamp, max_count=1))) except StopIteration: # It is for the case when no commits before the commit_time self.log.info("Trying to set the first commit in repo") self.commit_id = str(list(self.repo.iter_commits('--all'))[-1]) - self.log.info(f"Revert commit by time to: {datetime.fromtimestamp(commit_time)}") + self.log.info(f"Revert commit by time to: {datetime.fromtimestamp(time_stamp)}") def get_time(self, commit_id=None): """ @@ -311,9 +327,7 @@ def extract_all_repos(self): if repo.is_trigger: git_commit_date = repo.get_time() - commit_timestamp = self.commit_time.timestamp() \ - if self.commit_time \ - else git_commit_date + commit_time = self.commit_time or git_commit_date for repo in self.repo_states: if repo.commit_id == 'HEAD': @@ -322,11 +336,11 @@ def extract_all_repos(self): if not repo.is_branch_exist(repo.branch_name): raise BranchDoesNotExistException( f'Release branch {repo.branch_name} does not exist in the repo {repo.repo_name}') - repo.change_repo_state(branch_name=repo.branch_name, commit_time=commit_timestamp) + repo.change_repo_state(branch_name=repo.branch_name, commit_time=commit_time) # if parameters '--commit-time', '--changed-repo' and '--repo-states' didn't set # then variable 'commit_timestamp' is 'None' and 'HEAD' revisions be used elif repo.repo_name not in THIRD_PARTY: - repo.change_repo_state(commit_time=commit_timestamp) + repo.change_repo_state(commit_time=commit_time) def save_repo_states(self, sources_file, trigger): """ @@ -430,13 +444,13 @@ def get_last_committer_of_file_line(repo, file_path, line): :type repo: pathlib.Path :param file_path: path to a file from repo - :return file_path: pathlib.Path + :type file_path: pathlib.Path :param line: Line number - :return line: String + :type line: String - :return email of last committer - :rtype None + :return: email of last committer + :rtype: Union[str, NoneType] """ if file_path.exists() and not file_path.is_dir(): @@ -468,14 +482,14 @@ def get_commits(repo_path, commit_from, commit_to=None): :rtype: git.Commit | List """ - r = git.Repo(str(repo_path)) + repo = git.Repo(str(repo_path)) if commit_to: - commits = list(r.iter_commits(f'{commit_from}..{commit_to}')) - commits.append(r.commit(commit_from)) + commits = list(repo.iter_commits(f'{commit_from}..{commit_to}')) + commits.append(repo.commit(commit_from)) return commits - return r.commit(commit_from) + return repo.commit(commit_from) @staticmethod def get_commit_number(repo_path): @@ -496,15 +510,29 @@ def get_commit_number(repo_path): return str(git_repo.rev_list('--count', 'HEAD')) -def extract_repo(root_repo_dir, repo_name, url, branch='master', commit_id='HEAD'): +def extract_repo(root_repo_dir, repo_name, url, branch='master', commit_id=None, commit_time=None): """ Clone or update a repository to the specified state + :param root_repo_dir: Directory where repositories will be cloned + + :param repo_name: Name of repository + + :param branch: Branch of repository + + :param commit_id: Commit ID + + :param commit_time: Time for changing repo state. Can be used instead of commit_id + :type commit_time: Union[str, datetime, timestamp] + :return: None """ + if commit_id is None and commit_time is None: + commit_id = 'HEAD' + elif commit_id and commit_time: + commit_time = None # commit_id and commit_time can be incompatible + repo = GitRepo(root_repo_dir=root_repo_dir, repo_name=repo_name, branch=branch, url=url, commit_id=commit_id) repo.prepare_repo() - repo.change_repo_state() - - + repo.change_repo_state(commit_time=commit_time) diff --git a/common/helper.py b/common/helper.py index 4f70fc43..ed948cc8 100644 --- a/common/helper.py +++ b/common/helper.py @@ -27,12 +27,12 @@ import shutil import stat import tarfile +import json +import subprocess from enum import Enum -from shutil import copystat, Error, copy2 from zipfile import ZipFile, ZIP_DEFLATED + from common.system_info import get_os_version -import json -import subprocess class UnsupportedArchiveError(Exception): @@ -244,7 +244,7 @@ def make_archive(path, data_to_archive): pkg.add(path_to_archive, arcname=pack_as) elif path.suffix == '.zip': _zip_data(path_to_archive, pack_as, pkg) - except: + except Exception: log.exception("Can not pack results") no_errors = False @@ -334,7 +334,7 @@ def extract_archive(archive_path, extract_to, exclude=None): # shutil.copytree function with extension # TODO merge with copytree from test scripts -def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, +def copytree(src, dst, symlinks=False, ignore=None, copy_function=shutil.copy2, ignore_dangling_symlinks=False): """Recursively copy a directory tree. @@ -392,7 +392,7 @@ def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, # code with a custom `copy_function` may rely on copytree # doing the right thing. os.symlink(linkto, dstname) - copystat(srcname, dstname, follow_symlinks=not symlinks) + shutil.copystat(srcname, dstname, follow_symlinks=not symlinks) else: # ignore dangling symlink if the flag is on if not os.path.exists(linkto) and ignore_dangling_symlinks: @@ -410,18 +410,18 @@ def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, copy_function(srcname, dstname) # catch the Error from the recursive copytree so that we can # continue with other files - except Error as err: + except shutil.Error as err: errors.extend(err.args[0]) except OSError as why: errors.append((srcname, dstname, str(why))) try: - copystat(src, dst) + shutil.copystat(src, dst) except OSError as why: # Copying file access times may fail on Windows if getattr(why, 'winerror', None) is None: errors.append((src, dst, str(why))) if errors: - raise Error(errors) + raise shutil.Error(errors) return dst @@ -500,7 +500,7 @@ def copy_win_files(repos_dir, build_dir): ignore=ignore_files) -def _remove_directory(path): +def remove_directory(path): """ Removes directory: different from shutil.rmtree() in following aspects: * if file or directory does not have write permission - tries to set this permission @@ -511,61 +511,62 @@ def _remove_directory(path): @type path: C{string} """ - caught_exception = None - try: - this_dir, child_dirs, files = next(os.walk(path)) - except StopIteration: - raise OSError(2, 'Path does not exist', path) - for childDir in child_dirs: - try: - path_to_remove = os.path.join(this_dir, childDir) - if os.path.islink(path_to_remove): - os.unlink(path_to_remove) - else: - remove_directory(path_to_remove) - except Exception as e: - if not caught_exception: - caught_exception = e - for f in files: - file_path = os.path.join(this_dir, f) + def rm_dir(path): + caught_exception = None try: - os.unlink(file_path) - except: + this_dir, child_dirs, files = next(os.walk(path)) + except StopIteration: + return + + for childDir in child_dirs: try: - if not os.access(file_path, os.W_OK) and not os.path.islink(file_path): - os.chmod(file_path, stat.S_IWRITE) - os.unlink(file_path) - except Exception as e: + path_to_remove = os.path.join(this_dir, childDir) + if os.path.islink(path_to_remove): + os.unlink(path_to_remove) + else: + remove_directory(path_to_remove) + except Exception as exc: if not caught_exception: - caught_exception = e - try: - os.rmdir(this_dir) - except: + caught_exception = exc + for file_name in files: + file_path = os.path.join(this_dir, file_name) + try: + os.unlink(file_path) + except: + try: + if not os.access(file_path, os.W_OK) and not os.path.islink(file_path): + os.chmod(file_path, stat.S_IWRITE) + os.unlink(file_path) + except Exception as exc: + if not caught_exception: + caught_exception = exc try: - if not os.access(this_dir, os.W_OK): - os.chmod(this_dir, stat.S_IWRITE) os.rmdir(this_dir) - except Exception as e: - if not caught_exception: - caught_exception = e - - if caught_exception: - raise caught_exception + except: + try: + if not os.access(this_dir, os.W_OK): + os.chmod(this_dir, stat.S_IWRITE) + os.rmdir(this_dir) + except Exception as exc: + if not caught_exception: + caught_exception = exc + if caught_exception: + # TODO: real exception should be re-raised + raise OSError(caught_exception) -if os.name == 'nt': - def remove_directory(path): + if os.name == 'nt': try: - return _remove_directory(path) + return rm_dir(path) except WindowsError as err: # err == 206 - Path too long. Try unicode version of the function - # err == 123 - The filename, directory name, or volume label syntax is incorrect. Try unicode version of the function + # err == 123 - The filename, directory name, or volume label syntax is incorrect. + # Try unicode version of the function # err == 3 - The system cannot find the path specified if err in [3, 206, 123] and (not isinstance(path, str) or not path.startswith(u'\\\\?\\')): - return _remove_directory(u'\\\\?\\' + os.path.abspath(str(path, errors='ignore'))) + return rm_dir(u'\\\\?\\' + os.path.abspath(str(path, errors='ignore'))) raise -else: - remove_directory = _remove_directory + return rm_dir(path) def rotate_dir(directory: pathlib.Path) -> bool: @@ -606,17 +607,18 @@ def update_json(check_type, success, output, json_path): if path.exists(): try: - with open(path) as f: - data = json.load(f) + with open(path) as json_file_obj: + data = json.load(json_file_obj) data.update(new_data) - with open(path, "w") as f: - json.dump(data, f, indent=4, sort_keys=True) + with open(path, "w") as json_file_obj: + json.dump(data, json_file_obj, indent=4, sort_keys=True) except Exception: + # TODO: Add error handling return False else: - with open(path, "w") as f: - json.dump(new_data, f, indent=4, sort_keys=True) + with open(path, "w") as json_file_obj: + json.dump(new_data, json_file_obj, indent=4, sort_keys=True) return True diff --git a/requirements.txt b/requirements.txt index 181dd4da..634a68be 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,5 @@ tenacity==4.5.0 distro==1.3.0 PyYAML==5.1 pylint==2.3.0 +python-dateutil==2.8.0 requests==2.22.0 \ No newline at end of file