neural-amp-modeler

Neural network emulator for guitar amplifiers
Log | Files | Refs | README | LICENSE

_version.py (3895B)


      1 # File: _version.py
      2 # Created Date: Tuesday December 20th 2022
      3 # Author: Steven Atkinson (steven@atkinson.mn)
      4 
      5 """
      6 Version utility
      7 """
      8 
      9 from typing import Optional as _Optional
     10 
     11 from .._version import __version__
     12 
     13 
     14 class IncomparableVersionError(ValueError):
     15     """
     16     Error raised when two versions can't be compared.
     17     """
     18 
     19     pass
     20 
     21 
     22 class Version:
     23     def __init__(self, major: int, minor: int, patch: int, dev: _Optional[str] = None):
     24         self.major = major
     25         self.minor = minor
     26         self.patch = patch
     27         self.dev = dev
     28         self.dev_int = self._parse_dev_int(dev)
     29 
     30     @classmethod
     31     def from_string(cls, s: str):
     32         def special_case(s: str) -> _Optional[dict]:
     33             """
     34             Regretful hacks
     35             """
     36             # It seems like the git repo isn't accessible to setuptools_scm's version
     37             # guesser, so it comes up with this during install:
     38             if s == "0.1.dev1":
     39                 # This will be fine.
     40                 return {
     41                     "major": 0,
     42                     "minor": 1,
     43                     "patch": 0,
     44                     "dev": "dev1"
     45                 }
     46             return None
     47         
     48         if special_case(s) is not None:
     49             return cls(**special_case(s))
     50 
     51         # Typical
     52         parts = s.split(".")
     53         if len(parts) == 3:  # e.g. "0.7.1"
     54             dev = None
     55         elif len(parts) == 4:  # e.g. "0.7.1.dev7"
     56             dev = parts[3]
     57         else:
     58             raise ValueError(f"Invalid version string {s}")
     59         try:
     60             major, minor, patch = [int(x) for x in parts[:3]]
     61         except ValueError as e:
     62             raise ValueError(f"Failed to parse version from string '{s}':\n{e}")
     63         return cls(major=major, minor=minor, patch=patch, dev=dev)
     64 
     65     def __eq__(self, other) -> bool:
     66         return (
     67             self.major == other.major
     68             and self.minor == other.minor
     69             and self.patch == other.patch
     70             and self.dev == other.dev
     71         )
     72 
     73     def __lt__(self, other) -> bool:
     74         if self == other:
     75             return False
     76         if self.major != other.major:
     77             return self.major < other.major
     78         if self.minor != other.minor:
     79             return self.minor < other.minor
     80         if self.patch != other.patch:
     81             return self.patch < other.patch
     82         if self.dev != other.dev:
     83             # None is defined as least
     84             if self.dev is None and other.dev is not None:
     85                 return True
     86             elif self.dev is not None and other.dev is None:
     87                 return False
     88             assert self.dev is not None
     89             assert other.dev is not None
     90             if self.dev_int is None:
     91                 raise IncomparableVersionError(
     92                     f"Version {str(self)} has incomparable dev version {self.dev}"
     93                 )
     94             if other.dev_int is None:
     95                 raise IncomparableVersionError(
     96                     f"Version {str(other)} has incomparable dev version {other.dev}"
     97                 )
     98             return self.dev_int < other.dev_int
     99         raise RuntimeError(
    100             f"Unhandled comparison between versions {str(self)} and {str(other)}"
    101         )
    102 
    103     def __str__(self) -> str:
    104         return f"{self.major}.{self.minor}.{self.patch}"
    105 
    106     def _parse_dev_int(self, dev: _Optional[str]) -> _Optional[int]:
    107         """
    108         Turn the string into an int that can be compared if possible.
    109         """
    110         if dev is None:
    111             return None
    112         if not isinstance(dev, str):
    113             raise TypeError(f"Invalid dev string type {type(dev)}")
    114         if not dev.startswith("dev") or len(dev) <= 3:  # "misc", "dev", etc
    115             return None
    116         return int(dev.removeprefix("dev"))
    117 
    118 
    119 PROTEUS_VERSION = Version(4, 0, 0)
    120 
    121 
    122 def get_current_version() -> Version:
    123     return Version.from_string(__version__)