|
| 1 | +#!/usr/bin/env python3 |
| 2 | +"""Script to update boto* library constraints aws hard-coded variable.""" |
| 3 | + |
| 4 | +import logging |
| 5 | +import os |
| 6 | +import re |
| 7 | + |
| 8 | +from functools import partial |
| 9 | +from pathlib import PosixPath |
| 10 | + |
| 11 | + |
| 12 | +FORMAT = "[%(asctime)s] - %(message)s" |
| 13 | +logging.basicConfig(format=FORMAT) |
| 14 | +logger = logging.getLogger("update_aws_user_agent") |
| 15 | +logger.setLevel(logging.DEBUG) |
| 16 | + |
| 17 | +MIN_BOTOCORE_RE = re.compile(r"MINIMUM_BOTOCORE_VERSION( *)=( *)[\"|'][0-9\.]+[\"|']") |
| 18 | +MIN_BOTO3_RE = re.compile(r"MINIMUM_BOTO3_VERSION( *)=( *)[\"|'][0-9\.]+[\"|']") |
| 19 | + |
| 20 | + |
| 21 | +def replace_vars(values: dict[str, str], line: str) -> str: |
| 22 | + """Replace a variable from a string. |
| 23 | +
|
| 24 | + :param values: A dictionary of values to search into strin. |
| 25 | + :param line: The string to replace values in. |
| 26 | + :returns: The updated string. |
| 27 | + """ |
| 28 | + res = None |
| 29 | + for var, value in values.items(): |
| 30 | + match = re.match(rf"^{var}([ =\"']*)[0-9\.]+(.*)", line) |
| 31 | + if match: |
| 32 | + res = var + match.group(1) + value + match.group(2) |
| 33 | + break |
| 34 | + return line if res is None else res |
| 35 | + |
| 36 | + |
| 37 | +def update_single_file(path: str, values: dict[str, str]) -> None: |
| 38 | + """Update requirement file with boto3 and botocore constraints. |
| 39 | +
|
| 40 | + :param path: The path to the file to update. |
| 41 | + :param values: dictionary of boto3 and botocore constraints |
| 42 | + """ |
| 43 | + with open(path, encoding="utf-8") as file_read: |
| 44 | + content = file_read.read().split("\n") |
| 45 | + new_content = list(map(partial(replace_vars, values), content)) |
| 46 | + if new_content != content: |
| 47 | + with open(path, "w", encoding="utf-8") as file_write: |
| 48 | + file_write.write("\n".join(new_content)) |
| 49 | + logger.info("%s => updated", path) |
| 50 | + |
| 51 | + |
| 52 | +def update_tests_constraints(boto3_version: str, botocore_version: str) -> None: |
| 53 | + """Update boto3 and botocore constraints from requirement file. |
| 54 | +
|
| 55 | + :param boto3_version: The boto3 version to define. |
| 56 | + :param botocore_version: The boto core version to define. |
| 57 | + """ |
| 58 | + boto_values = {"boto3": boto3_version, "botocore": botocore_version} |
| 59 | + for file in ("tests/unit/constraints.txt", "tests/integration/constraints.txt"): |
| 60 | + update_single_file(file, boto_values) |
| 61 | + |
| 62 | + min_boto_values = { |
| 63 | + "MINIMUM_BOTO3_VERSION": boto3_version, |
| 64 | + "MINIMUM_BOTOCORE_VERSION": botocore_version, |
| 65 | + } |
| 66 | + for root, _, files in os.walk("plugins"): |
| 67 | + for name in files: |
| 68 | + if not name.endswith(".py"): |
| 69 | + continue |
| 70 | + update_single_file(os.path.join(root, name), min_boto_values) |
| 71 | + |
| 72 | + |
| 73 | +def read_boto_version() -> tuple[str, str]: |
| 74 | + """Read boto version constraints from requirement file. |
| 75 | +
|
| 76 | + :returns: Tuple of boto3 and botocore version constraints |
| 77 | + """ |
| 78 | + botocore_regex = re.compile(r"^botocore[>=<]+([0-9\.]+)", re.MULTILINE | re.IGNORECASE) |
| 79 | + boto3_regex = re.compile(r"^boto3[>=<]+([0-9\.]+)", re.MULTILINE | re.IGNORECASE) |
| 80 | + |
| 81 | + with PosixPath("requirements.txt").open(encoding="utf-8") as file_desc: |
| 82 | + content = file_desc.read() |
| 83 | + m_boto3 = boto3_regex.search(content) |
| 84 | + m_botocore = botocore_regex.search(content) |
| 85 | + return m_boto3.group(1) if m_boto3 else "", m_botocore.group(1) if m_botocore else "" |
| 86 | + |
| 87 | + |
| 88 | +def main() -> None: |
| 89 | + """Read boto constraints and update variables accordingly.""" |
| 90 | + boto3_version, botocore_version = read_boto_version() |
| 91 | + logger.info("boto3='%s' - botocore='%s'", boto3_version, botocore_version) |
| 92 | + update_tests_constraints(boto3_version, botocore_version) |
| 93 | + |
| 94 | + |
| 95 | +if __name__ == "__main__": |
| 96 | + main() |
0 commit comments