mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
135 lines
4.2 KiB
Python
Executable File
135 lines
4.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Manage hyperglass version across multiple files."""
|
|
|
|
# Standard Library
|
|
import re
|
|
from typing import Tuple, Union, Pattern
|
|
from pathlib import Path
|
|
|
|
# Third Party
|
|
import typer
|
|
|
|
PACKAGE_JSON = Path(__file__).parent / "hyperglass" / "ui" / "package.json"
|
|
PACKAGE_JSON_PATTERN = re.compile(r"\s+\"version\"\:\s\"(.+)\"\,$")
|
|
|
|
PYPROJECT_TOML = Path(__file__).parent / "pyproject.toml"
|
|
PYPROJECT_PATTERN = re.compile(r"^version\s\=\s\"(.+)\"$")
|
|
|
|
CONSTANTS = Path(__file__).parent / "hyperglass" / "constants.py"
|
|
CONSTANT_PATTERN = re.compile(r"^__version__\s\=\s\"(.+)\"$")
|
|
|
|
UPGRADES = (
|
|
("package.json", PACKAGE_JSON, PACKAGE_JSON_PATTERN),
|
|
("pyproject.toml", PYPROJECT_TOML, PYPROJECT_PATTERN),
|
|
("constants.py", CONSTANTS, CONSTANT_PATTERN),
|
|
)
|
|
|
|
cli = typer.Typer(name="version", no_args_is_help=True)
|
|
|
|
|
|
class Version:
|
|
"""Upgrade a file's version from one version to another."""
|
|
|
|
new_version: Union[str, int]
|
|
file: Path
|
|
line_pattern: Pattern[str]
|
|
old_version: Union[None, str, int] = None
|
|
_did_check: bool = False
|
|
_did_update: bool = False
|
|
|
|
def __init__(
|
|
self,
|
|
*,
|
|
name: str,
|
|
new_version: Union[str, int],
|
|
line_pattern: Union[Pattern, str],
|
|
file: Union[Path, str],
|
|
) -> None:
|
|
"""Initialize version manager."""
|
|
|
|
self.name = name
|
|
self.new_version = new_version
|
|
|
|
if isinstance(file, Path):
|
|
self.file = file
|
|
elif isinstance(file, str):
|
|
self.file = Path(file)
|
|
else:
|
|
raise TypeError(f"'{repr(file)}' must be a string or Path object")
|
|
|
|
if isinstance(line_pattern, Pattern):
|
|
self.line_pattern = line_pattern
|
|
elif isinstance(line_pattern, str):
|
|
self.line_pattern = re.compile(line_pattern)
|
|
else:
|
|
raise TypeError(f"'{repr(line_pattern)}' is not a supported pattern")
|
|
|
|
def __enter__(self) -> "Version":
|
|
"""Exit context manager for 0.01% better DX."""
|
|
return self
|
|
|
|
def __exit__(self, *args, **kwargs) -> None:
|
|
"""Exit context manager for 0.01% better DX."""
|
|
pass
|
|
|
|
def __str__(self) -> str:
|
|
"""Represent the state and/or action taken."""
|
|
if self._did_update:
|
|
old, new = self.upgrade_path
|
|
return f"Upgraded {self.name} from {old} → {new}"
|
|
if self._did_check:
|
|
return f"No update required for {self.name} from version {self.old_version}"
|
|
|
|
return f"{self.name} has not been checked"
|
|
|
|
def upgrade(self) -> None:
|
|
"""Find a matching current version and upgrade it to the new version."""
|
|
with self.file.open("r+") as file:
|
|
found_match = False
|
|
lines = file.readlines()
|
|
self._did_check = True
|
|
|
|
for idx, line in enumerate(lines):
|
|
match = self.line_pattern.match(line)
|
|
if match:
|
|
old_version = match.group(1).strip()
|
|
try:
|
|
old_version = int(old_version)
|
|
except ValueError:
|
|
# Old version can't be converted to an integer, which is fine.
|
|
pass
|
|
self.old_version = old_version
|
|
|
|
if self.old_version != self.new_version:
|
|
lines[idx] = re.sub(old_version, self.new_version, line)
|
|
found_match = True
|
|
break
|
|
|
|
if found_match:
|
|
file.seek(0)
|
|
file.writelines(lines)
|
|
file.truncate()
|
|
self._did_update = True
|
|
|
|
@property
|
|
def upgrade_path(self) -> Tuple[Union[str, int], Union[str, int]]:
|
|
"""Get the old and new versions."""
|
|
return (self.old_version, self.new_version)
|
|
|
|
|
|
def update_versions(new_version: str) -> None:
|
|
"""Update hyperglass version in all package files."""
|
|
for name, file, pattern in UPGRADES:
|
|
with Version(
|
|
name=name,
|
|
file=file,
|
|
line_pattern=pattern,
|
|
new_version=new_version,
|
|
) as version:
|
|
version.upgrade()
|
|
typer.echo(str(version))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
typer.run(update_versions)
|