diff --git a/game/savecompat.py b/game/savecompat.py new file mode 100644 index 00000000..5388dd24 --- /dev/null +++ b/game/savecompat.py @@ -0,0 +1,48 @@ +"""Tools for aiding in save compat removal after compatibility breaks.""" +from collections import Callable +from typing import TypeVar + +from game.version import MAJOR_VERSION + +ReturnT = TypeVar("ReturnT") + + +class DeprecatedSaveCompatError(RuntimeError): + def __init__(self, function_name: str) -> None: + super().__init__( + f"{function_name} has save compat code for a different major version." + ) + + +def has_save_compat_for( + major: int, +) -> Callable[[Callable[..., ReturnT]], Callable[..., ReturnT]]: + """Declares a function or method as having save compat code for a given version. + + If the function has save compatibility for the current major version, there is no + change in behavior. + + If the function has save compatibility for a *different* (future or past) major + version, DeprecatedSaveCompatError will be raised during startup. Since a break in + save compatibility is the definition of a major version break, there's no need to + keep around old save compat code; it only serves to mask initialization bugs. + + Args: + major: The major version for which the decorated function has save + compatibility. + + Returns: + The decorated function or method. + + Raises: + DeprecatedSaveCompatError: The decorated function has save compat code for + another version of liberation, and that code (and the decorator declaring it) + should be removed from this branch. + """ + + def decorator(func: Callable[..., ReturnT]) -> Callable[..., ReturnT]: + if major != MAJOR_VERSION: + raise DeprecatedSaveCompatError(func.__name__) + return func + + return decorator diff --git a/game/version.py b/game/version.py index c25490e0..7c989e2a 100644 --- a/game/version.py +++ b/game/version.py @@ -1,8 +1,15 @@ from pathlib import Path +MAJOR_VERSION = 5 +MINOR_VERSION = 0 +MICRO_VERSION = 0 + + def _build_version_string() -> str: - components = ["5.0.0"] + components = [ + ".".join(str(v) for v in (MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION)) + ] build_number_path = Path("resources/buildnumber") if build_number_path.exists(): with build_number_path.open("r") as build_number_file: