diff --git a/.bandit.yaml b/.bandit.yaml deleted file mode 100644 index 91fa86c2e..000000000 --- a/.bandit.yaml +++ /dev/null @@ -1,6 +0,0 @@ -skips: - - B101 # Use of assert detected. - - B603 # subprocess call - check for execution of untrusted input - - B607 # Starting a process with a partial executable path - - B108 # Probable insecure usage of temp file/directory. - - B113 # Requests call without timeout: the check is buggy... diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 69a18dec8..6ce705a54 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -100,35 +100,25 @@ repos: rev: v0.1.8 hooks: - id: ripsecrets - - repo: https://github.com/asottile/pyupgrade - rev: v3.19.0 + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.8.1 hooks: - - id: pyupgrade + - id: ruff-format args: - - --py39-plus - - repo: https://github.com/PyCQA/autoflake - rev: v2.3.1 - hooks: - - id: autoflake - - repo: https://github.com/PyCQA/isort - rev: 5.13.2 - hooks: - - id: isort - - repo: https://github.com/psf/black - rev: 24.10.0 - hooks: - - id: black + - --line-length=110 - repo: https://github.com/PyCQA/prospector rev: v1.13.3 hooks: - id: prospector args: - - --tool=pydocstyle + - --tool=ruff - --die-on-tool-error - --output-format=pylint additional_dependencies: - prospector-profile-duplicated==1.8.0 # pypi - - prospector-profile-utils==1.12.2 # pypi + - prospector-profile-utils==1.13.0 # pypi + - ruff==0.8.1 # pypi - repo: https://github.com/mheap/json-schema-spell-checker rev: main hooks: diff --git a/.prospector.yaml b/.prospector.yaml index 97cfd0278..4d3c0e35d 100644 --- a/.prospector.yaml +++ b/.prospector.yaml @@ -2,23 +2,12 @@ inherits: - utils:base - utils:no-design-checks - utils:fix + - utils:unsafe - duplicated -doc-warnings: true - ignore-paths: - c2cciutils/configuration.py -pylint: - disable: - - missing-module-docstring - bandit: - options: - config: .bandit.yaml - -pycodestyle: disable: - # Buggy checks that don't detect strings - - W604 # backticks are deprecated, use 'repr()' - - E221 # multiple spaces before operator + - B113 # Call to requests without timeout (didn't work) diff --git a/c2cciutils/__init__.py b/c2cciutils/__init__.py index bf2565953..49b924aec 100644 --- a/c2cciutils/__init__.py +++ b/c2cciutils/__init__.py @@ -1,6 +1,4 @@ -""" -c2cciutils shared utils function. -""" +"""c2cciutils shared utils function.""" import glob import json @@ -18,9 +16,7 @@ def get_repository() -> str: - """ - Get the current GitHub repository like `organization/project`. - """ + """Get the current GitHub repository like `organization/project`.""" if "GITHUB_REPOSITORY" in os.environ: return os.environ["GITHUB_REPOSITORY"] @@ -44,11 +40,12 @@ def merge(default_config: Any, config: Any) -> Any: Arguments: default_config: The default config that will be applied config: The base config, will be modified + """ if not isinstance(default_config, dict) or not isinstance(config, dict): return config - for key in default_config.keys(): + for key in default_config: if key not in config: config[key] = default_config[key] else: @@ -73,9 +70,7 @@ def get_master_branch(repo: list[str]) -> tuple[str, bool]: def get_config() -> c2cciutils.configuration.Configuration: - """ - Get the configuration, with project and auto detections. - """ + """Get the configuration, with project and auto detections.""" config: c2cciutils.configuration.Configuration = {} if os.path.exists("ci/config.yaml"): with open("ci/config.yaml", encoding="utf-8") as open_file: @@ -155,6 +150,7 @@ def error( line: The line number of the error col: The column number of the error error_type: The kind of error (error or warning) + """ result = "" on_ci = os.environ.get("CI", "false").lower() == "true" @@ -197,6 +193,7 @@ def compile_re(config: c2cciutils.configuration.VersionTransform, prefix: str = prefix: The version prefix Return the compiled transform config. + """ result = [] for conf in config: @@ -226,6 +223,7 @@ def match( Returns the re match object, the matched config and the value as a tuple On no match it returns None, value + """ for conf in config: matched = conf["from"].match(value) @@ -243,6 +241,7 @@ def does_match(value: str, config: list[VersionTransform]) -> bool: config: The result of `compile` Returns True it it does match else False + """ matched, _, _ = match(value, config) return matched is not None @@ -262,6 +261,7 @@ def get_value(matched: Optional[Match[str]], config: Optional[VersionTransform], value: The default value on returned no match Return the value + """ return matched.expand(config.get("to", r"\1")) if matched is not None and config is not None else value @@ -272,6 +272,7 @@ def print_versions(config: c2cciutils.configuration.PrintVersions) -> bool: Arguments: config: The print configuration + """ for version in config.get("versions", c2cciutils.configuration.PRINT_VERSIONS_VERSIONS_DEFAULT): try: @@ -310,6 +311,7 @@ def gopass(key: str, default: Optional[str] = None) -> Optional[str]: default: the value to return if gopass is not found Return the value + """ try: return subprocess.check_output(["gopass", "show", key]).strip().decode() @@ -326,6 +328,7 @@ def gopass_put(secret: str, key: str) -> None: Arguments: secret: The secret value key: The key + """ subprocess.check_output(["gopass", "insert", "--force", key], input=secret.encode()) @@ -338,6 +341,7 @@ def add_authorization_header(headers: dict[str, str]) -> dict[str, str]: headers: The headers Return the headers (to be chained) + """ try: token = ( @@ -375,6 +379,7 @@ def graphql(query_file: str, variables: dict[str, Any], default: Any = None) -> Return the data result In case of error it throw an exception + """ with open(os.path.join(os.path.dirname(__file__), query_file), encoding="utf-8") as query_open: query = query_open.read() diff --git a/c2cciutils/applications_definition.py b/c2cciutils/applications_definition.py index 49fec80e6..a0f63c265 100644 --- a/c2cciutils/applications_definition.py +++ b/c2cciutils/applications_definition.py @@ -1,6 +1,4 @@ -""" -Automatically generated file from a JSON schema. -""" +"""Automatically generated file from a JSON schema.""" from typing import Literal, TypedDict, Union diff --git a/c2cciutils/configuration.py b/c2cciutils/configuration.py index c8102f522..87c578587 100644 --- a/c2cciutils/configuration.py +++ b/c2cciutils/configuration.py @@ -1,6 +1,4 @@ -""" -Automatically generated file from a JSON schema. -""" +"""Automatically generated file from a JSON schema.""" from typing import Any, Literal, TypedDict, Union @@ -721,7 +719,7 @@ class _PrintVersionsVersionsItem(TypedDict, total=False): class _PublishDockerConfigSnyk(TypedDict, total=False): - """Checks the published images with Snyk""" + """Checks the published images with Snyk.""" monitor_args: Union["_PublishDockerSnykMonitorArgsOneof0", "_PublishDockerSnykMonitorArgsOneof1"] """ diff --git a/c2cciutils/env.py b/c2cciutils/env.py index 187463caa..2f76b4b09 100644 --- a/c2cciutils/env.py +++ b/c2cciutils/env.py @@ -10,9 +10,7 @@ class PrintVersions: - """ - Print some tools versions. - """ + """Print some tools versions.""" def __init__(self, config: c2cciutils.configuration.PrintVersions) -> None: """Construct.""" @@ -24,9 +22,7 @@ def __call__(self) -> None: class PrintConfig: - """ - Print the configuration. - """ + """Print the configuration.""" def __init__(self, config: c2cciutils.configuration.Configuration) -> None: """Construct.""" @@ -40,49 +36,37 @@ def __call__(self) -> None: def print_environment_variables() -> None: - """ - Print the environment variables. - """ + """Print the environment variables.""" for name, value in sorted(os.environ.items()): if name != "GITHUB_EVENT": print(f"{name}: {value}") def print_github_event_file() -> None: - """ - Print the GitHub event file. - """ + """Print the GitHub event file.""" if "GITHUB_EVENT_PATH" in os.environ: with open(os.environ["GITHUB_EVENT_PATH"], encoding="utf-8") as event: print(event.read()) def print_github_event_object() -> None: - """ - Print the GitHub event object. - """ + """Print the GitHub event object.""" github_event = json.loads(os.environ["GITHUB_EVENT"]) print(yaml.dump(github_event, indent=2)) def print_python_package_version() -> None: - """ - Print the version of the Python packages. - """ + """Print the version of the Python packages.""" subprocess.run(["python3", "-m", "pip", "freeze", "--all"]) # pylint: disable=subprocess-run-check def print_node_package_version() -> None: - """ - Print the version of the Python packages. - """ + """Print the version of the Python packages.""" subprocess.run(["npm", "list", "--global"]) # pylint: disable=subprocess-run-check def print_debian_package_version() -> None: - """ - Print the version of the Python packages. - """ + """Print the version of the Python packages.""" subprocess.run(["dpkg", "--list"]) # pylint: disable=subprocess-run-check diff --git a/c2cciutils/lib/docker.py b/c2cciutils/lib/docker.py index ca0c92b90..50f9b898c 100644 --- a/c2cciutils/lib/docker.py +++ b/c2cciutils/lib/docker.py @@ -1,6 +1,4 @@ -""" -Some utility functions for Docker images. -""" +"""Some utility functions for Docker images.""" import os import subprocess # nosec: B404 @@ -102,9 +100,7 @@ def get_dpkg_packages_versions( def get_versions_config() -> tuple[dict[str, dict[str, str]], bool]: - """ - Get the versions from the config file. - """ + """Get the versions from the config file.""" if os.path.exists("ci/dpkg-versions.yaml"): with open("ci/dpkg-versions.yaml", encoding="utf-8") as versions_file: return ( diff --git a/c2cciutils/lib/oidc.py b/c2cciutils/lib/oidc.py index 82abd5303..84a2f9513 100755 --- a/c2cciutils/lib/oidc.py +++ b/c2cciutils/lib/oidc.py @@ -154,8 +154,10 @@ def pypi_login() -> None: Connect to PyPI using OpenID Connect and mint a token for the user. See Also + -------- - https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect - https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-pypi + """ pypirc_filename = os.path.expanduser("~/.pypirc") diff --git a/c2cciutils/publish.py b/c2cciutils/publish.py index 3ae07c5e6..71425c2ff 100644 --- a/c2cciutils/publish.py +++ b/c2cciutils/publish.py @@ -1,6 +1,4 @@ -""" -The publishing functions. -""" +"""The publishing functions.""" import argparse import datetime @@ -10,11 +8,11 @@ import re import subprocess # nosec import sys -import tomllib import uuid from typing import Optional import ruamel.yaml +import tomllib from google.auth.transport.requests import Request from google.oauth2.credentials import Credentials from google_auth_oauthlib.flow import InstalledAppFlow @@ -24,17 +22,13 @@ class GoogleCalendar: - """ - Interact with the Google Calendar API. - """ + """Interact with the Google Calendar API.""" # pylint: disable=too-many-instance-attributes def __init__(self) -> None: - """ - Initialize. - """ + """Initialize.""" self.scopes = ["https://www.googleapis.com/auth/calendar"] # in fact it is better to hard-code this - self.credentials_pickle_file = os.environ.get("TMP_CREDS_FILE", f"/tmp/{uuid.uuid4()}.pickle") + self.credentials_pickle_file = os.environ.get("TMP_CREDS_FILE", f"/tmp/{uuid.uuid4()}.pickle") # noqa: S108 self.credentials_json_file = os.environ.get( "GOOGLE_CREDS_JSON_FILE", "~/google-credentials-c2cibot.json" ) # used to refresh the refresh_token or to initialize the credentials the first time @@ -62,15 +56,13 @@ def __init__(self) -> None: self.service = build("calendar", "v3", credentials=self.creds) def init_calendar_service(self) -> Credentials: # type: ignore - """ - Initialize the calendar service. - """ + """Initialize the calendar service.""" # The file token pickle stores the user's access and refresh tokens, and is # created automatically when the authorization flow completes for the first # time. if os.path.exists(self.credentials_pickle_file): with open(self.credentials_pickle_file, "rb") as token: - creds = pickle.load(token) # nosec + creds = pickle.load(token) # noqa: S301 # If there are no (valid) credentials available, let the user log in. if not creds or not creds.valid: # pylint: disable=possibly-used-before-assignment if creds and creds.expired and creds.refresh_token: @@ -95,9 +87,7 @@ def init_calendar_service(self) -> Credentials: # type: ignore pickle.dump(creds, token) def _update_creds(self) -> None: - """ - Update the credentials. - """ + """Update the credentials.""" self.client_id = self.creds.client_id self.client_secret = self.creds.client_secret self.token = self.creds.token @@ -105,9 +95,7 @@ def _update_creds(self) -> None: self.refresh_token = self.creds.refresh_token def print_all_calendars(self) -> None: - """ - Print all calendar events. - """ + """Print all calendar events.""" # list all the calendars that the user has access to. # used to debug credentials print("Getting list of calendars") @@ -129,6 +117,7 @@ def print_latest_events(self, time_min: Optional[datetime.datetime] = None) -> N Arguments: time_min: The time to be considered. + """ now = datetime.datetime.utcnow() if not time_min: @@ -163,6 +152,7 @@ def create_event( Arguments: summary: The event summary description: The event description + """ now = datetime.datetime.now() start = now.isoformat() @@ -178,9 +168,7 @@ def create_event( print(f"Created event with id: {event_result['id']}") def save_credentials_to_gopass(self) -> None: - """ - Save the calendar credentials to gopass. - """ + """Save the calendar credentials to gopass.""" objects_to_save = { "gs/ci/google_calendar/calendarId": self.calendar_id, "gs/ci/google_calendar/token": self.token, @@ -194,17 +182,13 @@ def save_credentials_to_gopass(self) -> None: c2cciutils.gopass_put(secret, key) def __del__(self) -> None: - """ - Delete the credentials file. - """ + """Delete the credentials file.""" if os.path.exists(self.credentials_pickle_file): os.remove(self.credentials_pickle_file) def main_calendar() -> None: - """ - Run the calendar main function. - """ + """Run the calendar main function.""" parser = argparse.ArgumentParser( description="Interact with google API for the Docker publishing calendar" ) @@ -254,6 +238,7 @@ def pip( version_branch, feature_branch, feature_tag (for pull request) publish: If False only check the package package: The package configuration + """ print(f"::group::{'Publishing' if publish else 'Checking'} '{package.get('path')}' to pypi") sys.stdout.flush() @@ -352,6 +337,7 @@ def docker( tag_src: The source tag (usually latest) dst_tags: Publish using the provided tags images_full: The list of published images (with tag), used to build the dispatch event + """ print( f"::group::Publishing {image_config['name']} to the server {name} using the tags {', '.join(dst_tags)}" @@ -411,6 +397,7 @@ def helm(folder: str, version: str, owner: str, repo: str, commit_sha: str, toke repo: The GitHub repository name commit_sha: The sha of the current commit token: The GitHub token + """ print(f"::group::Publishing Helm chart from '{folder}' to GitHub release") sys.stdout.flush() diff --git a/c2cciutils/scripts/__init__.py b/c2cciutils/scripts/__init__.py index acef9dd6c..4db9243af 100644 --- a/c2cciutils/scripts/__init__.py +++ b/c2cciutils/scripts/__init__.py @@ -1,3 +1 @@ -""" -The scripts main functions. -""" +"""The scripts main functions.""" diff --git a/c2cciutils/scripts/clean.py b/c2cciutils/scripts/clean.py index b90d089c1..744eec4c3 100644 --- a/c2cciutils/scripts/clean.py +++ b/c2cciutils/scripts/clean.py @@ -1,8 +1,6 @@ #!/usr/bin/env python3 -""" -The clean main function. -""" +"""The clean main function.""" import argparse import json @@ -24,6 +22,7 @@ def clean(image: str, tag: str, token: str) -> None: image: The image name that should be deleted (/) tag: The tag that should be deleted token: The token used to be authenticated on Docker hub + """ print(f"Delete image '{image}:{tag}'.") @@ -51,9 +50,7 @@ def clean(image: str, tag: str, token: str) -> None: def main() -> None: - """ - Run the main function. - """ + """Run the main function.""" parser = argparse.ArgumentParser( description=( "Clean the Docker images on Docker Hub for the branch we delete " @@ -87,10 +84,7 @@ def main() -> None: with open(os.environ["GITHUB_EVENT_PATH"], encoding="utf-8") as event_file: event = json.loads(event_file.read()) print(yaml.dump(event)) - if "pull_request" in event: - ref = str(event["number"]) - else: - ref = event["ref"] + ref = str(event["number"]) if "pull_request" in event else event["ref"] ref = ref.replace("/", "_") diff --git a/c2cciutils/scripts/docker_logs.py b/c2cciutils/scripts/docker_logs.py index 6a84a4045..3f45f904e 100644 --- a/c2cciutils/scripts/docker_logs.py +++ b/c2cciutils/scripts/docker_logs.py @@ -30,11 +30,11 @@ def main() -> None: # Store in /tmp/docker-logs-timestamp the current timestamp to avoid printing same logs multiple times. timestamp_args = [] - if os.path.exists("/tmp/docker-logs-timestamp"): - with open("/tmp/docker-logs-timestamp", encoding="utf-8") as timestamp_file: + if os.path.exists("/tmp/docker-logs-timestamp"): # noqa: S108 + with open("/tmp/docker-logs-timestamp", encoding="utf-8") as timestamp_file: # noqa: S108 timestamp_args = [f"--since={timestamp_file.read().strip()}Z"] - with open("/tmp/docker-logs-timestamp", "w", encoding="utf-8") as timestamp_file: + with open("/tmp/docker-logs-timestamp", "w", encoding="utf-8") as timestamp_file: # noqa: S108 timestamp_file.write(datetime.utcnow().isoformat()) for name in ( diff --git a/c2cciutils/scripts/env.py b/c2cciutils/scripts/env.py index 04fa0a006..25f438862 100644 --- a/c2cciutils/scripts/env.py +++ b/c2cciutils/scripts/env.py @@ -1,8 +1,6 @@ #!/usr/bin/env python3 -""" -The checker main function. -""" +"""The checker main function.""" import argparse @@ -10,9 +8,7 @@ def main() -> None: - """ - Run the checks. - """ + """Run the checks.""" parser = argparse.ArgumentParser(description="Print the environment information.") parser.parse_args() diff --git a/c2cciutils/scripts/k8s/__init__.py b/c2cciutils/scripts/k8s/__init__.py index 49abee23f..530aff901 100644 --- a/c2cciutils/scripts/k8s/__init__.py +++ b/c2cciutils/scripts/k8s/__init__.py @@ -1,3 +1 @@ -""" -The commands that can be used to test a chart on Kubernetes. -""" +"""The commands that can be used to test a chart on Kubernetes.""" diff --git a/c2cciutils/scripts/main.py b/c2cciutils/scripts/main.py index c2f01de40..3d35aa501 100644 --- a/c2cciutils/scripts/main.py +++ b/c2cciutils/scripts/main.py @@ -1,8 +1,6 @@ #!/usr/bin/env python3 -""" -The main function of some utilities. -""" +"""The main function of some utilities.""" import argparse @@ -13,9 +11,7 @@ def main() -> None: - """ - Run the utilities. - """ + """Run the utilities.""" parser = argparse.ArgumentParser(description="Some utils of c2cciutils.") parser.add_argument("--get-config", action="store_true", help="display the current config") parser.add_argument("--version", action="store_true", help="display the current version") diff --git a/c2cciutils/scripts/publish.py b/c2cciutils/scripts/publish.py index f3db17aa1..ffc2bd0cd 100644 --- a/c2cciutils/scripts/publish.py +++ b/c2cciutils/scripts/publish.py @@ -1,8 +1,6 @@ #!/usr/bin/env python3 -""" -The publish script. -""" +"""The publish script.""" import argparse import os @@ -34,6 +32,7 @@ def match(tpe: str, base_re: str) -> Optional[Match[str]]: Arguments: tpe: The type of ref we want to match (heads, tag, ...) base_re: The regular expression to match the value + """ if base_re[0] == "^": base_re = base_re[1:] @@ -50,6 +49,7 @@ def to_version(full_config: c2cciutils.configuration.Configuration, value: str, full_config: The full configuration value: The value to be transformed kind: The name of the transformer in the configuration + """ item_re = c2cciutils.compile_re( cast( @@ -63,9 +63,7 @@ def to_version(full_config: c2cciutils.configuration.Configuration, value: str, def main() -> None: - """ - Run the publish. - """ + """Run the publish.""" parser = argparse.ArgumentParser(description="Publish the project.") parser.add_argument("--group", default="default", help="The publishing group") parser.add_argument("--version", help="The version to publish to") @@ -311,23 +309,22 @@ def main() -> None: conf, name, image_conf, tag_src, tags, images_full ) - if google_calendar_publish: - if version_type in google_calendar_config.get( - "on", c2cciutils.configuration.PUBLISH_GOOGLE_CALENDAR_ON_DEFAULT - ): - if not google_calendar: - google_calendar = GoogleCalendar() - summary = f"{image_conf['name']}:{', '.join(tags_calendar)}" - description = "\n".join( - [ - f"Published the image {image_conf['name']}", - f"Published on: {', '.join(docker_config['repository'].keys())}", - f"With tags: {', '.join(tags_calendar)}", - f"For version type: {version_type}", - ] - ) + if google_calendar_publish and version_type in google_calendar_config.get( + "on", c2cciutils.configuration.PUBLISH_GOOGLE_CALENDAR_ON_DEFAULT + ): + if not google_calendar: + google_calendar = GoogleCalendar() + summary = f"{image_conf['name']}:{', '.join(tags_calendar)}" + description = "\n".join( + [ + f"Published the image {image_conf['name']}", + f"Published on: {', '.join(docker_config['repository'].keys())}", + f"With tags: {', '.join(tags_calendar)}", + f"For version type: {version_type}", + ] + ) - google_calendar.create_event(summary, description) + google_calendar.create_event(summary, description) if args.dry_run: sys.exit(0) diff --git a/c2cciutils/scripts/trigger_image_update.py b/c2cciutils/scripts/trigger_image_update.py index 23f7f2877..602b77973 100644 --- a/c2cciutils/scripts/trigger_image_update.py +++ b/c2cciutils/scripts/trigger_image_update.py @@ -1,8 +1,6 @@ #!/usr/bin/env python3 -""" -Trigger an image update on the argocd repository. -""" +"""Trigger an image update on the argocd repository.""" import argparse import os.path @@ -60,10 +58,8 @@ def main() -> None: def dispatch(repository: str, event_type: str, images_full: list[str]) -> None: - """ - Trigger an image update on the argocd repository. - """ - id_ = random.randint(1, 100000) # nosec + """Trigger an image update on the argocd repository.""" + id_ = random.randint(1, 100000) # noqa: S311 print(f"Triggering {event_type}:{id_} on {repository} with {','.join(images_full)}") response = requests.post( diff --git a/c2cciutils/scripts/version.py b/c2cciutils/scripts/version.py index 92c12d549..595d12afc 100644 --- a/c2cciutils/scripts/version.py +++ b/c2cciutils/scripts/version.py @@ -149,9 +149,11 @@ def main() -> None: stabilization_branches_with_master = [*stabilization_branches, repo.get("master_branch", "master")] for labels in mra.gh_json("label", ["name"], "list"): - if labels["name"].startswith("backport "): - if labels["name"].replace("backport ", "") not in stabilization_branches_with_master: - mra.gh("label", "delete", labels["name"], "--yes") + if ( + labels["name"].startswith("backport ") + and labels["name"].replace("backport ", "") not in stabilization_branches_with_master + ): + mra.gh("label", "delete", labels["name"], "--yes") for branch in stabilization_branches_with_master: mra.gh( diff --git a/ci/requires_release b/ci/requires_release deleted file mode 100755 index 2f8fcf56d..000000000 --- a/ci/requires_release +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python3 - -import datetime -from distutils.version import LooseVersion - -import requests - - -def main() -> None: - url = "https://pypi.org/pypi/c2cciutils/json" - data = requests.get(url, timeout=int(os.environ.get("C2CCIUTILS_TIMEOUT", "30"))).json() - versions = [LooseVersion(v) for v in data["releases"].keys()] - versions = [v for v in versions if len(v.version) == 4] - versions = sorted(versions) - version = versions[-1].vstring - - date_str = version.split(".dev")[1][:8] - date_obj = datetime.datetime.strptime(date_str, "%Y%m%d") - days = (datetime.datetime.now() - date_obj).days - required = "true" if days > 30 else "false" - - print(f"days: {days}") - print(f"required: {required}") - with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as output_file: - output_file.write(f"days={days}\n") - output_file.write(f"required={required}\n") - - -if __name__ == "__main__": - main() diff --git a/example-project/project/__init__.py b/example-project/project/__init__.py index 7b527d842..76fd503e4 100644 --- a/example-project/project/__init__.py +++ b/example-project/project/__init__.py @@ -1,3 +1 @@ -""" -Example project. -""" +"""Example project.""" diff --git a/poetry.lock b/poetry.lock index 75b71db69..02cc4f6b8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "annotated-types" @@ -1185,6 +1185,7 @@ pylint-flask = "0.6" pyroma = {version = ">=2.4", optional = true, markers = "extra == \"with-pyroma\" or extra == \"with_everything\""} PyYAML = "*" requirements-detector = ">=1.3.2" +ruff = {version = "*", optional = true, markers = "extra == \"with-ruff\" or extra == \"with_everything\""} setoptconf-tmp = ">=0.3.1,<0.4.0" toml = ">=0.10.2,<0.11.0" @@ -1895,6 +1896,33 @@ files = [ {file = "ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f"}, ] +[[package]] +name = "ruff" +version = "0.8.1" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.8.1-py3-none-linux_armv6l.whl", hash = "sha256:fae0805bd514066f20309f6742f6ee7904a773eb9e6c17c45d6b1600ca65c9b5"}, + {file = "ruff-0.8.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8a4f7385c2285c30f34b200ca5511fcc865f17578383db154e098150ce0a087"}, + {file = "ruff-0.8.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:cd054486da0c53e41e0086e1730eb77d1f698154f910e0cd9e0d64274979a209"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2029b8c22da147c50ae577e621a5bfbc5d1fed75d86af53643d7a7aee1d23871"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2666520828dee7dfc7e47ee4ea0d928f40de72056d929a7c5292d95071d881d1"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:333c57013ef8c97a53892aa56042831c372e0bb1785ab7026187b7abd0135ad5"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:288326162804f34088ac007139488dcb43de590a5ccfec3166396530b58fb89d"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b12c39b9448632284561cbf4191aa1b005882acbc81900ffa9f9f471c8ff7e26"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:364e6674450cbac8e998f7b30639040c99d81dfb5bbc6dfad69bc7a8f916b3d1"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b22346f845fec132aa39cd29acb94451d030c10874408dbf776af3aaeb53284c"}, + {file = "ruff-0.8.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b2f2f7a7e7648a2bfe6ead4e0a16745db956da0e3a231ad443d2a66a105c04fa"}, + {file = "ruff-0.8.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:adf314fc458374c25c5c4a4a9270c3e8a6a807b1bec018cfa2813d6546215540"}, + {file = "ruff-0.8.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a885d68342a231b5ba4d30b8c6e1b1ee3a65cf37e3d29b3c74069cdf1ee1e3c9"}, + {file = "ruff-0.8.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d2c16e3508c8cc73e96aa5127d0df8913d2290098f776416a4b157657bee44c5"}, + {file = "ruff-0.8.1-py3-none-win32.whl", hash = "sha256:93335cd7c0eaedb44882d75a7acb7df4b77cd7cd0d2255c93b28791716e81790"}, + {file = "ruff-0.8.1-py3-none-win_amd64.whl", hash = "sha256:2954cdbe8dfd8ab359d4a30cd971b589d335a44d444b6ca2cb3d1da21b75e4b6"}, + {file = "ruff-0.8.1-py3-none-win_arm64.whl", hash = "sha256:55873cc1a473e5ac129d15eccb3c008c096b94809d693fc7053f588b67822737"}, + {file = "ruff-0.8.1.tar.gz", hash = "sha256:3583db9a6450364ed5ca3f3b4225958b24f78178908d5c4bc0f46251ccca898f"}, +] + [[package]] name = "secretstorage" version = "3.3.3" @@ -2208,4 +2236,4 @@ version = ["multi-repo-automation"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<4.0" -content-hash = "c99c0c5ab172f7e1fecd33f5b1d4d0712fa9030df5003e39bad047229a3eb99d" +content-hash = "d6cd64f9e95d171040590e188c40c6bc9593b21fba0b394c032ab8428cf1fe02" diff --git a/pyproject.toml b/pyproject.toml index b744a09d7..1a09c9f39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -86,7 +86,7 @@ pr_checks = [] version = ["multi-repo-automation"] [tool.poetry.group.dev.dependencies] -prospector = { version = "1.13.3", extras = ["with-bandit", "with-mypy", "with-pyroma"] } +prospector = { version = "1.13.3", extras = ["with-bandit", "with-mypy", "with-pyroma", "with-ruff"] } prospector-profile-duplicated = "1.8.0" prospector-profile-utils = "1.13.0" types-requests = "2.32.0.20241016"