misc.python.materialize.mz_version
Version types
1# Copyright Materialize, Inc. and contributors. All rights reserved. 2# 3# Use of this software is governed by the Business Source License 4# included in the LICENSE file at the root of this repository. 5# 6# As of the Change Date specified in that file, in accordance with 7# the Business Source License, use of this software will be governed 8# by the Apache License, Version 2.0. 9 10"""Version types""" 11 12from __future__ import annotations 13 14import json 15import subprocess 16from typing import TypeVar 17 18try: 19 from semver.version import Version 20except ImportError: 21 from semver import VersionInfo as Version # type: ignore 22 23T = TypeVar("T", bound="TypedVersionBase") 24 25 26class TypedVersionBase(Version): 27 """Typed version, can be parsed from version string""" 28 29 @classmethod 30 def get_prefix(cls) -> str: 31 raise NotImplementedError(f"Not implemented in {cls}") 32 33 @classmethod 34 def create( 35 cls: type[T], major: int, minor: int, patch: int, prerelease: str | None = None 36 ) -> T: 37 prerelease_suffix = f"-{prerelease}" if prerelease is not None else "" 38 return cls.parse( 39 f"{cls.get_prefix()}{major}.{minor}.{patch}{prerelease_suffix}" 40 ) 41 42 @classmethod 43 def parse_without_prefix( 44 cls: type[T], version_without_prefix: str, drop_dev_suffix: bool = False 45 ) -> T: 46 version = f"{cls.get_prefix()}{version_without_prefix}" 47 return cls.parse(version, drop_dev_suffix=drop_dev_suffix) 48 49 @classmethod 50 def parse(cls: type[T], version: str, drop_dev_suffix: bool = False) -> T: 51 """Parses a version string with prefix, for example: v0.45.0-dev (f01773cb1) or v0.115.0-dev.0""" 52 expected_prefix = cls.get_prefix() 53 if not version.startswith(expected_prefix): 54 raise ValueError( 55 f"Invalid version string '{version}', expected prefix '{expected_prefix}'" 56 ) 57 version = version.removeprefix(expected_prefix) 58 if " " in version: 59 version, git_hash = version.split(" ") 60 if not git_hash[0] == "(" or not git_hash[-1] == ")": 61 raise ValueError(f"Invalid mz version string: {version}") 62 # Hash ignored 63 64 if drop_dev_suffix: 65 version, _, _ = version.partition("-dev") 66 67 return super().parse(version) 68 69 @classmethod 70 def try_parse( 71 cls: type[T], version: str, drop_dev_suffix: bool = False 72 ) -> T | None: 73 """Parses a version string but returns empty if that fails""" 74 try: 75 return cls.parse(version, drop_dev_suffix=drop_dev_suffix) 76 except ValueError: 77 return None 78 79 @classmethod 80 def is_valid_version_string(cls, version: str) -> bool: 81 return cls.try_parse(version) is not None 82 83 def str_without_prefix(self) -> str: 84 return super().__str__() 85 86 def __str__(self) -> str: 87 return f"{self.get_prefix()}{self.str_without_prefix()}" 88 89 def is_dev_version(self) -> bool: 90 return self.prerelease is not None 91 92 93class MzVersion(TypedVersionBase): 94 """Version of Materialize, can be parsed from version string, SQL, cargo""" 95 96 @classmethod 97 def get_prefix(cls) -> str: 98 return "v" 99 100 @classmethod 101 def parse_mz(cls: type[T], version: str, drop_dev_suffix: bool = False) -> T: 102 """Parses a version string with prefix, for example: v0.45.0-dev (f01773cb1) or v0.115.0-dev.0""" 103 return cls.parse(version=version, drop_dev_suffix=drop_dev_suffix) 104 105 @classmethod 106 def parse_cargo(cls) -> MzVersion: 107 """Uses the cargo mz-environmentd package info to get the version of current source code state""" 108 metadata = json.loads( 109 subprocess.check_output( 110 ["cargo", "metadata", "--no-deps", "--format-version=1"] 111 ) 112 ) 113 for package in metadata["packages"]: 114 if package["name"] == "mz-environmentd": 115 return cls.parse_without_prefix(package["version"]) 116 else: 117 raise ValueError("No mz-environmentd version found in cargo metadata") 118 119 120class MzCliVersion(TypedVersionBase): 121 """Version of Materialize APT""" 122 123 @classmethod 124 def get_prefix(cls) -> str: 125 return "mz-v" 126 127 128class MzLspServerVersion(TypedVersionBase): 129 """Version of Materialize LSP Server""" 130 131 @classmethod 132 def get_prefix(cls) -> str: 133 return "mz-lsp-server-v" 134 135 136class MzDebugVersion(TypedVersionBase): 137 """Version of Materialize Debug Tool""" 138 139 @classmethod 140 def get_prefix(cls) -> str: 141 return "mz-debug-v"
class
TypedVersionBase(semver.version.Version):
27class TypedVersionBase(Version): 28 """Typed version, can be parsed from version string""" 29 30 @classmethod 31 def get_prefix(cls) -> str: 32 raise NotImplementedError(f"Not implemented in {cls}") 33 34 @classmethod 35 def create( 36 cls: type[T], major: int, minor: int, patch: int, prerelease: str | None = None 37 ) -> T: 38 prerelease_suffix = f"-{prerelease}" if prerelease is not None else "" 39 return cls.parse( 40 f"{cls.get_prefix()}{major}.{minor}.{patch}{prerelease_suffix}" 41 ) 42 43 @classmethod 44 def parse_without_prefix( 45 cls: type[T], version_without_prefix: str, drop_dev_suffix: bool = False 46 ) -> T: 47 version = f"{cls.get_prefix()}{version_without_prefix}" 48 return cls.parse(version, drop_dev_suffix=drop_dev_suffix) 49 50 @classmethod 51 def parse(cls: type[T], version: str, drop_dev_suffix: bool = False) -> T: 52 """Parses a version string with prefix, for example: v0.45.0-dev (f01773cb1) or v0.115.0-dev.0""" 53 expected_prefix = cls.get_prefix() 54 if not version.startswith(expected_prefix): 55 raise ValueError( 56 f"Invalid version string '{version}', expected prefix '{expected_prefix}'" 57 ) 58 version = version.removeprefix(expected_prefix) 59 if " " in version: 60 version, git_hash = version.split(" ") 61 if not git_hash[0] == "(" or not git_hash[-1] == ")": 62 raise ValueError(f"Invalid mz version string: {version}") 63 # Hash ignored 64 65 if drop_dev_suffix: 66 version, _, _ = version.partition("-dev") 67 68 return super().parse(version) 69 70 @classmethod 71 def try_parse( 72 cls: type[T], version: str, drop_dev_suffix: bool = False 73 ) -> T | None: 74 """Parses a version string but returns empty if that fails""" 75 try: 76 return cls.parse(version, drop_dev_suffix=drop_dev_suffix) 77 except ValueError: 78 return None 79 80 @classmethod 81 def is_valid_version_string(cls, version: str) -> bool: 82 return cls.try_parse(version) is not None 83 84 def str_without_prefix(self) -> str: 85 return super().__str__() 86 87 def __str__(self) -> str: 88 return f"{self.get_prefix()}{self.str_without_prefix()}" 89 90 def is_dev_version(self) -> bool: 91 return self.prerelease is not None
Typed version, can be parsed from version string
@classmethod
def
create( cls: type[~T], major: int, minor: int, patch: int, prerelease: str | None = None) -> ~T:
@classmethod
def
parse_without_prefix( cls: type[~T], version_without_prefix: str, drop_dev_suffix: bool = False) -> ~T:
@classmethod
def
parse(cls: type[~T], version: str, drop_dev_suffix: bool = False) -> ~T:
50 @classmethod 51 def parse(cls: type[T], version: str, drop_dev_suffix: bool = False) -> T: 52 """Parses a version string with prefix, for example: v0.45.0-dev (f01773cb1) or v0.115.0-dev.0""" 53 expected_prefix = cls.get_prefix() 54 if not version.startswith(expected_prefix): 55 raise ValueError( 56 f"Invalid version string '{version}', expected prefix '{expected_prefix}'" 57 ) 58 version = version.removeprefix(expected_prefix) 59 if " " in version: 60 version, git_hash = version.split(" ") 61 if not git_hash[0] == "(" or not git_hash[-1] == ")": 62 raise ValueError(f"Invalid mz version string: {version}") 63 # Hash ignored 64 65 if drop_dev_suffix: 66 version, _, _ = version.partition("-dev") 67 68 return super().parse(version)
Parses a version string with prefix, for example: v0.45.0-dev (f01773cb1) or v0.115.0-dev.0
@classmethod
def
try_parse( cls: type[~T], version: str, drop_dev_suffix: bool = False) -> Optional[~T]:
70 @classmethod 71 def try_parse( 72 cls: type[T], version: str, drop_dev_suffix: bool = False 73 ) -> T | None: 74 """Parses a version string but returns empty if that fails""" 75 try: 76 return cls.parse(version, drop_dev_suffix=drop_dev_suffix) 77 except ValueError: 78 return None
Parses a version string but returns empty if that fails
94class MzVersion(TypedVersionBase): 95 """Version of Materialize, can be parsed from version string, SQL, cargo""" 96 97 @classmethod 98 def get_prefix(cls) -> str: 99 return "v" 100 101 @classmethod 102 def parse_mz(cls: type[T], version: str, drop_dev_suffix: bool = False) -> T: 103 """Parses a version string with prefix, for example: v0.45.0-dev (f01773cb1) or v0.115.0-dev.0""" 104 return cls.parse(version=version, drop_dev_suffix=drop_dev_suffix) 105 106 @classmethod 107 def parse_cargo(cls) -> MzVersion: 108 """Uses the cargo mz-environmentd package info to get the version of current source code state""" 109 metadata = json.loads( 110 subprocess.check_output( 111 ["cargo", "metadata", "--no-deps", "--format-version=1"] 112 ) 113 ) 114 for package in metadata["packages"]: 115 if package["name"] == "mz-environmentd": 116 return cls.parse_without_prefix(package["version"]) 117 else: 118 raise ValueError("No mz-environmentd version found in cargo metadata")
Version of Materialize, can be parsed from version string, SQL, cargo
@classmethod
def
parse_mz(cls: type[~T], version: str, drop_dev_suffix: bool = False) -> ~T:
101 @classmethod 102 def parse_mz(cls: type[T], version: str, drop_dev_suffix: bool = False) -> T: 103 """Parses a version string with prefix, for example: v0.45.0-dev (f01773cb1) or v0.115.0-dev.0""" 104 return cls.parse(version=version, drop_dev_suffix=drop_dev_suffix)
Parses a version string with prefix, for example: v0.45.0-dev (f01773cb1) or v0.115.0-dev.0
106 @classmethod 107 def parse_cargo(cls) -> MzVersion: 108 """Uses the cargo mz-environmentd package info to get the version of current source code state""" 109 metadata = json.loads( 110 subprocess.check_output( 111 ["cargo", "metadata", "--no-deps", "--format-version=1"] 112 ) 113 ) 114 for package in metadata["packages"]: 115 if package["name"] == "mz-environmentd": 116 return cls.parse_without_prefix(package["version"]) 117 else: 118 raise ValueError("No mz-environmentd version found in cargo metadata")
Uses the cargo mz-environmentd package info to get the version of current source code state
121class MzCliVersion(TypedVersionBase): 122 """Version of Materialize APT""" 123 124 @classmethod 125 def get_prefix(cls) -> str: 126 return "mz-v"
Version of Materialize APT
129class MzLspServerVersion(TypedVersionBase): 130 """Version of Materialize LSP Server""" 131 132 @classmethod 133 def get_prefix(cls) -> str: 134 return "mz-lsp-server-v"
Version of Materialize LSP Server
137class MzDebugVersion(TypedVersionBase): 138 """Version of Materialize Debug Tool""" 139 140 @classmethod 141 def get_prefix(cls) -> str: 142 return "mz-debug-v"
Version of Materialize Debug Tool