Preserve all version fields (#286)
Up to now extra version fields were ignored: only name and date fields were accepted. This changes that by retaining the full JSON data when reading the file, making it possible in the future to support custom fields. This also fixes a bug with versions having released on the same date: they was not ordered as expected (reverse order).
This commit is contained in:
@@ -11,25 +11,28 @@ VERSIONS_PATH = Path(os.environ.get("VERSIONS_PATH", "releases"))
|
||||
|
||||
|
||||
class ProductVersion:
|
||||
def __init__(self, product: "Product", name: str, date: datetime) -> None:
|
||||
def __init__(self, product: "Product", data: dict) -> None:
|
||||
self.product = str(product)
|
||||
self.name = name
|
||||
self.date = date
|
||||
self.data = data
|
||||
|
||||
@staticmethod
|
||||
def from_json(product: "Product", data: dict) -> "ProductVersion":
|
||||
name = data["name"]
|
||||
date = datetime.strptime(data["date"], "%Y-%m-%d").replace(tzinfo=timezone.utc)
|
||||
return ProductVersion(product, name, date)
|
||||
def of(product: "Product", name: str, date: datetime) -> "ProductVersion":
|
||||
return ProductVersion(product, {
|
||||
"name": name,
|
||||
"date": date.strftime("%Y-%m-%d"),
|
||||
})
|
||||
|
||||
def __dict__(self) -> dict:
|
||||
return {
|
||||
"name": self.name,
|
||||
"date": self.date.strftime("%Y-%m-%d"),
|
||||
}
|
||||
def name(self) -> str:
|
||||
return self.data["name"]
|
||||
|
||||
def date(self) -> datetime:
|
||||
return datetime.strptime(self.data["date"], "%Y-%m-%d").replace(tzinfo=timezone.utc)
|
||||
|
||||
def replace_date(self, date: datetime) -> None:
|
||||
self.data["date"] = date.strftime("%Y-%m-%d")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"{self.product}#{self.name} ({self.date})"
|
||||
return f"{self.product}#{self.name()} ({self.date()})"
|
||||
|
||||
|
||||
class Product:
|
||||
@@ -46,8 +49,8 @@ class Product:
|
||||
if product.versions_path.is_file():
|
||||
with product.versions_path.open() as f:
|
||||
for json_version in json.load(f)["versions"].values():
|
||||
version = ProductVersion.from_json(product, json_version)
|
||||
product.versions[version.name] = version
|
||||
version = ProductVersion(product, json_version)
|
||||
product.versions[version.name()] = version
|
||||
logging.info(f"loaded versions data for {product} from {product.versions_path}")
|
||||
else:
|
||||
logging.warning(f"no versions data found for {product} at {product.versions_path}")
|
||||
@@ -57,31 +60,21 @@ class Product:
|
||||
def has_version(self, version: str) -> bool:
|
||||
return version in self.versions
|
||||
|
||||
def get_version_date(self, version: str) -> datetime:
|
||||
return self.versions[version].date if version in self.versions else None
|
||||
def get_version(self, version: str) -> ProductVersion:
|
||||
return self.versions[version] if version in self.versions else None
|
||||
|
||||
def declare_version(self, version: str, date: datetime) -> None:
|
||||
if version in self.versions:
|
||||
if self.versions[version].date != date:
|
||||
logging.warning(f"overwriting {version} ({self.get_version_date(version)} -> {date}) for {self}")
|
||||
else:
|
||||
return # already declared
|
||||
|
||||
logging.info(f"adding version {version} ({date}) to {self}")
|
||||
self.versions[version] = ProductVersion(self, version, date)
|
||||
if version in self.versions and self.versions[version].date() != date:
|
||||
logging.info(f"overwriting {version} ({self.get_version(version).date()} -> {date}) for {self}")
|
||||
self.versions[version].replace_date(date)
|
||||
else:
|
||||
logging.info(f"adding version {version} ({date}) to {self}")
|
||||
self.versions[version] = ProductVersion.of(self, version, date)
|
||||
|
||||
def declare_versions(self, dates_by_version: dict[str, datetime]) -> None:
|
||||
for (version, date) in dates_by_version.items():
|
||||
self.declare_version(version, date)
|
||||
|
||||
def replace_version(self, version: str, date: datetime) -> None:
|
||||
if version not in self.versions:
|
||||
msg = f"version {version} cannot be replaced as it does not exist for {self}"
|
||||
raise ValueError(msg)
|
||||
|
||||
logging.info(f"replacing version {version} ({self.get_version_date(version)} -> {date}) in {self}")
|
||||
self.versions[version].date = date
|
||||
|
||||
def remove_version(self, version: str) -> None:
|
||||
if not self.has_version(version):
|
||||
logging.warning(f"version {version} cannot be removed as it does not exist for {self}")
|
||||
@@ -91,10 +84,10 @@ class Product:
|
||||
|
||||
def write(self) -> None:
|
||||
# sort by date then version (desc)
|
||||
ordered_versions = sorted(self.versions.values(), key=lambda v: (v.date, v.name), reverse=True)
|
||||
ordered_versions = sorted(self.versions.values(), key=lambda v: (v.date(), v.name()), reverse=True)
|
||||
with self.versions_path.open("w") as f:
|
||||
f.write(json.dumps({
|
||||
"versions": {version.name: version.__dict__() for version in ordered_versions},
|
||||
"versions": {version.name(): version.data for version in ordered_versions},
|
||||
}, indent=2))
|
||||
logging.info("::endgroup::")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user