Refactor scripts arguments handling (#456)
- remove the use of environment variables to get directory paths, - make use of arguments / argparse instead of environment variables in `update.py` and `report.py`, - automatically guess the data directory in `latest.py` based on the script's location, - propagate log level to auto scripts, - move `list_configs_from_argv` from `endoflife` module to `releasedata` module, - use `list_products` in `latest.py` to load the product's frontmatters.
This commit is contained in:
@@ -1,8 +1,5 @@
|
||||
import itertools
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
@@ -15,8 +12,6 @@ DEFAULT_VERSION_REGEX = r"^v?(?P<major>[1-9]\d*)\.(?P<minor>\d+)(\.(?P<patch>\d+
|
||||
DEFAULT_VERSION_PATTERN = re.compile(DEFAULT_VERSION_REGEX)
|
||||
DEFAULT_VERSION_TEMPLATE = "{{major}}{% if minor %}.{{minor}}{% if patch %}.{{patch}}{% if tiny %}.{{tiny}}{% endif %}{% endif %}{% endif %}"
|
||||
|
||||
PRODUCTS_PATH = Path(os.environ.get("PRODUCTS_PATH", "website/products"))
|
||||
|
||||
|
||||
class AutoConfig:
|
||||
def __init__(self, product: str, data: dict) -> None:
|
||||
@@ -58,9 +53,9 @@ class AutoConfig:
|
||||
|
||||
|
||||
class ProductFrontmatter:
|
||||
def __init__(self, name: str) -> None:
|
||||
self.name: str = name
|
||||
self.path: Path = PRODUCTS_PATH / f"{name}.md"
|
||||
def __init__(self, path: Path) -> None:
|
||||
self.path: Path = path
|
||||
self.name: str = path.stem
|
||||
|
||||
self.data = None
|
||||
if self.path.is_file():
|
||||
@@ -109,37 +104,19 @@ class ProductFrontmatter:
|
||||
return None
|
||||
|
||||
|
||||
def list_products(products_filter: str = None) -> list[ProductFrontmatter]:
|
||||
"""Return a list of products that are using the same given update method."""
|
||||
def list_products(products_dir: Path, product_name: str = None) -> list[ProductFrontmatter]:
|
||||
product_names = [product_name] if product_name else sorted([p.stem for p in products_dir.glob("*.md")])
|
||||
|
||||
products = []
|
||||
|
||||
for product_file in sorted(PRODUCTS_PATH.glob("*.md")):
|
||||
product_name = product_file.stem
|
||||
if products_filter and product_name != products_filter:
|
||||
continue
|
||||
|
||||
for product_name in product_names:
|
||||
try:
|
||||
products.append(ProductFrontmatter(product_name))
|
||||
products.append(ProductFrontmatter(products_dir / f"{product_name}.md"))
|
||||
except Exception as e:
|
||||
logging.exception(f"failed to load product data for {product_name}: {e}")
|
||||
|
||||
return products
|
||||
|
||||
|
||||
def list_configs(products_filter: str = None, methods_filter: str = None, urls_filter: str = None) -> list[AutoConfig]:
|
||||
"""Return a list of auto configs, filtering by product name, method, and URL."""
|
||||
products = list_products(products_filter)
|
||||
configs_by_product = [p.auto_configs(methods_filter, urls_filter) for p in products]
|
||||
return list(itertools.chain.from_iterable(configs_by_product)) # flatten the list of lists
|
||||
|
||||
|
||||
def list_configs_from_argv() -> list[AutoConfig]:
|
||||
products_filter = sys.argv[1] if len(sys.argv) > 1 else None
|
||||
methods_filter = sys.argv[2] if len(sys.argv) > 1 else None
|
||||
urls_filter = sys.argv[3] if len(sys.argv) > 2 else None
|
||||
return list_configs(products_filter, methods_filter, urls_filter)
|
||||
|
||||
|
||||
def to_identifier(s: str) -> str:
|
||||
"""Convert a string to a valid endoflife.date identifier."""
|
||||
identifier = s.strip().lower()
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from types import TracebackType
|
||||
from typing import Optional, Type
|
||||
|
||||
# Do not update the format: it's also used to declare groups in the GitHub Actions logs.
|
||||
logging.basicConfig(format="%(message)s", level=logging.INFO)
|
||||
from . import endoflife
|
||||
|
||||
VERSIONS_PATH = Path(os.environ.get("VERSIONS_PATH", "releases"))
|
||||
SRC_DIR = Path('src')
|
||||
DATA_DIR = Path('releases')
|
||||
|
||||
|
||||
class ProductUpdateError(Exception):
|
||||
@@ -108,7 +109,7 @@ class ProductVersion:
|
||||
class ProductData:
|
||||
def __init__(self, name: str) -> None:
|
||||
self.name: str = name
|
||||
self.versions_path: Path = VERSIONS_PATH / f"{name}.json"
|
||||
self.versions_path: Path = DATA_DIR / f"{name}.json"
|
||||
self.releases = {}
|
||||
self.versions: dict[str, ProductVersion] = {}
|
||||
self.updated = False
|
||||
@@ -190,3 +191,21 @@ class ProductData:
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return self.name
|
||||
|
||||
|
||||
def list_configs_from_argv() -> list[endoflife.AutoConfig]:
|
||||
return parse_argv()[1]
|
||||
|
||||
def parse_argv() -> tuple[endoflife.ProductFrontmatter, list[endoflife.AutoConfig]]:
|
||||
parser = argparse.ArgumentParser(description=sys.argv[0])
|
||||
parser.add_argument('-p', '--product', required=True, help='path to the product')
|
||||
parser.add_argument('-m', '--method', required=True, help='method to filter by')
|
||||
parser.add_argument('-u', '--url', required=True, help='url to filter by')
|
||||
parser.add_argument('-v', '--verbose', action='store_true', help='enable verbose logging')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Do not update the format: it's also used to declare groups in the GitHub Actions logs.
|
||||
logging.basicConfig(format="%(message)s", level=(logging.DEBUG if args.verbose else logging.INFO))
|
||||
|
||||
product = endoflife.ProductFrontmatter(Path(args.product))
|
||||
return product, product.auto_configs(args.method, args.url)
|
||||
|
||||
Reference in New Issue
Block a user