From 798c298c5977153e89df425cd524e4ab16cd4356 Mon Sep 17 00:00:00 2001 From: Marc Wrobel Date: Sat, 30 Dec 2023 11:20:51 +0100 Subject: [PATCH] Enable flake8-datetimez linting rules (#267) See https://docs.astral.sh/ruff/rules/#flake8-datetimez-dtz. --- .ruff.toml | 1 + latest.py | 3 ++- src/artifactory.py | 3 +-- src/aws-lambda.py | 5 ++--- src/coldfusion.py | 13 ++++++------- src/common/dates.py | 12 +++++++++++- src/common/endoflife.py | 5 +++-- src/couchbase-server.py | 9 ++++----- src/haproxy.py | 5 ++--- src/maven.py | 4 ++-- 10 files changed, 34 insertions(+), 26 deletions(-) diff --git a/.ruff.toml b/.ruff.toml index 076063a0..fe4d3be2 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -7,6 +7,7 @@ select = [ "C4", # flake8-comprehensions "C90", # mccabe "COM", # flake8-commas + "DTZ", # flake8-commas "E", # pycodestyle errors "F", # pyflakes errors "I", # isort diff --git a/latest.py b/latest.py index 5854bfe2..36b31db3 100644 --- a/latest.py +++ b/latest.py @@ -172,7 +172,8 @@ def update_product(name: str, product_dir: Path, releases_dir: Path) -> None: # Print all unmatched versions released in the last 30 days if len(product.unmatched_versions) != 0: for version, date in product.unmatched_versions.items(): - days_since_release = (datetime.date.today() - date).days + today = datetime.datetime.now(tz=datetime.timezone.utc).date() + days_since_release = (today - date).days if days_since_release < 30: logging.warning(f"{name}:{version} ({date}) not included") github_output(f"{name}:{version} ({date})\n") diff --git a/src/artifactory.py b/src/artifactory.py index e965ac05..3e73df40 100644 --- a/src/artifactory.py +++ b/src/artifactory.py @@ -1,4 +1,3 @@ -import datetime from common import dates, endoflife from requests_html import HTMLSession @@ -21,7 +20,7 @@ for row in r.html.find('.informaltable tbody tr'): # 7.29.9 release date is wrong on https://jfrog.com/help/r/jfrog-release-information/artifactory-end-of-life. # Sent a mail to jfrog-help-center-feedback@jfrog.com to fix it, but in the meantime... -product.replace_version('7.29.9', datetime.datetime(2022, 1, 11)) +product.replace_version('7.29.9', dates.date(2022, 1, 11)) product.write() print("::endgroup::") diff --git a/src/aws-lambda.py b/src/aws-lambda.py index eed94f63..88679584 100644 --- a/src/aws-lambda.py +++ b/src/aws-lambda.py @@ -1,7 +1,6 @@ -import datetime from bs4 import BeautifulSoup -from common import endoflife, http +from common import dates, endoflife, http """Fetches AWS lambda runtimes from https://docs.aws.amazon.com. @@ -34,7 +33,7 @@ for table in soup.find_all("table"): if date is None: date = old_product.get_version_date(identifier) # else use the previously found date if date is None: - date = datetime.date.today() # else use today's date + date = dates.today() # else use today's date product.declare_version(identifier, date) diff --git a/src/coldfusion.py b/src/coldfusion.py index a3a4dbfe..dfda41c5 100644 --- a/src/coldfusion.py +++ b/src/coldfusion.py @@ -1,5 +1,4 @@ import re -from datetime import datetime from bs4 import BeautifulSoup from common import dates, endoflife, http @@ -24,12 +23,12 @@ VERSION_AND_DATE_PATTERN = re.compile(r"Release Date[,|:]? (.*?)\).*?Build Numbe # .0 release dates are not available in the release notes. FIXED_VERSIONS = { - "10.0.0": datetime(2012, 5, 15), # https://en.wikipedia.org/wiki/Adobe_ColdFusion#Adobe_ColdFusion_10 - "11.0.0": datetime(2014, 4, 29), # https://en.wikipedia.org/wiki/Adobe_ColdFusion#Adobe_ColdFusion_11 - "2016.0.0": datetime(2016, 2, 16), # https://en.wikipedia.org/wiki/Adobe_ColdFusion#Adobe_ColdFusion_(2016_Release) - "2018.0.0": datetime(2018, 7, 12), # https://coldfusion.adobe.com/2018/07/new-coldfusion-release-adds-performance-monitoring-toolset-for-measuring-monitoring-and-managing-high-performing-web-apps/ - "2021.0.0": datetime(2020, 11, 11), # https://community.adobe.com/t5/coldfusion-discussions/introducing-adobe-coldfusion-2021-release/m-p/11585468 - "2023.0.0": datetime(2022, 5, 16), # https://coldfusion.adobe.com/2023/05/coldfusion2023-release/ + "10.0.0": dates.date(2012, 5, 15), # https://en.wikipedia.org/wiki/Adobe_ColdFusion#Adobe_ColdFusion_10 + "11.0.0": dates.date(2014, 4, 29), # https://en.wikipedia.org/wiki/Adobe_ColdFusion#Adobe_ColdFusion_11 + "2016.0.0": dates.date(2016, 2, 16), # https://en.wikipedia.org/wiki/Adobe_ColdFusion#Adobe_ColdFusion_(2016_Release) + "2018.0.0": dates.date(2018, 7, 12), # https://coldfusion.adobe.com/2018/07/new-coldfusion-release-adds-performance-monitoring-toolset-for-measuring-monitoring-and-managing-high-performing-web-apps/ + "2021.0.0": dates.date(2020, 11, 11), # https://community.adobe.com/t5/coldfusion-discussions/introducing-adobe-coldfusion-2021-release/m-p/11585468 + "2023.0.0": dates.date(2022, 5, 16), # https://coldfusion.adobe.com/2023/05/coldfusion2023-release/ } product = endoflife.Product("coldfusion") diff --git a/src/common/dates.py b/src/common/dates.py index c9964d19..5dfd4b82 100644 --- a/src/common/dates.py +++ b/src/common/dates.py @@ -44,10 +44,20 @@ def parse_datetime(text: str, formats: list[str] = frozenset([ text = text.strip().replace(", ", " ").replace(". ", " ").replace("(", "").replace(")", "") for fmt in formats: try: - date = datetime.strptime(text, fmt) + date = datetime.strptime(text, fmt) # NOQA: DTZ007, timezone is handled below date = date.astimezone(timezone.utc) if to_utc else date return date except ValueError: pass raise ValueError(f"'{text}' could not be parsed as a date with any of the formats: {str(formats)}") + + +def date(year: int, month: int, day: int) -> datetime: + """Create a datetime object with the given year, month and day, at midnight.""" + return datetime(year, month, day, tzinfo=timezone.utc) + + +def today() -> datetime: + """Create a datetime object with today's date, at midnight.""" + return datetime.now(tz=timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0) diff --git a/src/common/endoflife.py b/src/common/endoflife.py index a242597f..8e9e9567 100644 --- a/src/common/endoflife.py +++ b/src/common/endoflife.py @@ -2,7 +2,7 @@ import json import logging import os import re -from datetime import datetime +from datetime import datetime, timezone from glob import glob import frontmatter @@ -84,7 +84,8 @@ class Product: if not os.path.isfile(product.versions_path): with open(product.versions_path) as f: for version, date in json.load(f).items(): - product.versions[version] = datetime.strptime(date, "%Y-%m-%d") + date_obj = datetime.strptime(date, "%Y-%m-%d").replace(tzinfo=timezone.utc) + product.versions[version] = date_obj logging.info(f"loaded versions data for {product.name} from {product.versions_path}") else: logging.warning(f"no versions data found for {product.name} at {product.versions_path}") diff --git a/src/couchbase-server.py b/src/couchbase-server.py index fe968d0d..3baad9c3 100644 --- a/src/couchbase-server.py +++ b/src/couchbase-server.py @@ -1,5 +1,4 @@ import re -from datetime import datetime from bs4 import BeautifulSoup from common import dates, endoflife, http @@ -13,10 +12,10 @@ Moreover dates are not accurate (only month and year are provided), so they are URLS = "https://docs.couchbase.com/server" VERSION_AND_DATE_PATTERN = re.compile(r"^Release (?P\d+\.\d+(\.\d+)?) \((?P.+)\)$") MANUAL_VERSIONS = { - "6.0.0": datetime(2018, 10, 31), # https://www.couchbase.com/blog/announcing-couchbase-6-0/ - "6.0.1": datetime(2019, 2, 15), # https://web.archive.org/web/20190307191211/https://docs.couchbase.com/server/6.0/release-notes/relnotes.html - "6.6.0": datetime(2020, 8, 12), # https://www.couchbase.com/blog/whats-new-and-improved-in-couchbase-server-6-6/ - "7.2.0": datetime(2023, 6, 1), # https://www.couchbase.com/blog/couchbase-capella-spring-release-72/ + "6.0.0": dates.date(2018, 10, 31), # https://www.couchbase.com/blog/announcing-couchbase-6-0/ + "6.0.1": dates.date(2019, 2, 15), # https://web.archive.org/web/20190307191211/https://docs.couchbase.com/server/6.0/release-notes/relnotes.html + "6.6.0": dates.date(2020, 8, 12), # https://www.couchbase.com/blog/whats-new-and-improved-in-couchbase-server-6-6/ + "7.2.0": dates.date(2023, 6, 1), # https://www.couchbase.com/blog/couchbase-capella-spring-release-72/ } product = endoflife.Product("couchbase-server") diff --git a/src/haproxy.py b/src/haproxy.py index 7a0ea3c7..a88cd7d0 100644 --- a/src/haproxy.py +++ b/src/haproxy.py @@ -1,8 +1,7 @@ import re -from datetime import datetime from bs4 import BeautifulSoup -from common import endoflife, http +from common import dates, endoflife, http CYCLE_PATTERN = re.compile(r"^(\d+\.\d+)/$") DATE_AND_VERSION_PATTERN = re.compile(r"^(\d{4})/(\d{2})/(\d{2})\s+:\s+(\d+\.\d+\.\d.?)$") # https://regex101.com/r/1JCnFC/1 @@ -29,7 +28,7 @@ for changelog in http.fetch_urls(changelog_urls): date_and_version_match = DATE_AND_VERSION_PATTERN.match(line) if date_and_version_match: year, month, day, version = date_and_version_match.groups() - product.declare_version(version, datetime(int(year), int(month), int(day))) + product.declare_version(version, dates.date(int(year), int(month), int(day))) product.write() print("::endgroup::") diff --git a/src/maven.py b/src/maven.py index c75f826e..46ac25eb 100644 --- a/src/maven.py +++ b/src/maven.py @@ -1,5 +1,5 @@ -import datetime import sys +from datetime import datetime, timezone from common import endoflife, http @@ -23,7 +23,7 @@ for product_name in endoflife.list_products(METHOD, p_filter): version_match = config.first_match(row["v"]) if version_match: version = config.render(version_match) - date = datetime.datetime.utcfromtimestamp(row["timestamp"] / 1000) + date = datetime.fromtimestamp(row["timestamp"] / 1000, tz=timezone.utc) product.declare_version(version, date) start += 100