def __init__ (self, namespace: str): self.Namespace = namespace # type: str self.Path = GetSitePath(namespace) # type: str try: self.Module = _GetSiteModule(namespace) # type: typing.Optional except Exception as e: if type(e) is not ModuleNotFoundError: print("Failed to import site module for '" + self.Namespace + "'\n" + Exceptions.FormatException(e), file = sys.stderr) self.Module = None # type: typing.Optional self.Data = _GetSiteData(self.Module) # type: typing.Dict[str, typing.Any] try: self.BuildModule = _GetBuildModule(namespace) # type: typing.Optional except Exception as e: if type(e) is not ModuleNotFoundError: print("Failed to import site build module for '" + self.Namespace + "'\n" + Exceptions.FormatException(e), file = sys.stderr) self.BuildModule = None # type: typing.Optional self._buildFunction = _GetBuildFunction(self.BuildModule) # type: typing.Optional[typing.Callable[[], bool]] self._buildPublishingFunction = _GetBuildPublishingFunction(self.BuildModule) # type: typing.Optional[typing.Callable[[], bool]] _sites.append(self)
def __init__(self, namespace: str): self.Namespace = namespace # type: str self.Path = GetModPath(namespace) # type: str self.ReleaseLatest = Distribution.GetReleaseLatest( namespace) # type: typing.Optional[Distribution.ModVersion] self.ReleaseVersions = Distribution.GetReleaseVersions( namespace ) # type: typing.Optional[typing.List[Distribution.ModVersion]] self.PreviewLatest = Distribution.GetPreviewLatest( namespace) # type: typing.Optional[Distribution.ModVersion] self.PreviewVersions = Distribution.GetPreviewVersions( namespace ) # type: typing.Optional[typing.List[Distribution.ModVersion]] self.Game = "The Sims 4" # type: str #TODO actually get the game for each mod. self.GameShortened = "S4" # type: str # Used in website page paths try: self.Module = _GetModModule(namespace) # type: typing.Optional except Exception as e: if type(e) is not ModuleNotFoundError: print("Failed to import mod module for '" + self.Namespace + "'\n" + Exceptions.FormatException(e), file=sys.stderr) self.Module = None # type: typing.Optional self.Data = _GetModData( self.Module) # type: typing.Dict[str, typing.Any] try: self.BuildModule = _GetBuildModule( namespace) # type: typing.Optional except Exception as e: if type(e) is not ModuleNotFoundError: print("Failed to import mod build module for '" + self.Namespace + "'\n" + Exceptions.FormatException(e), file=sys.stderr) self.BuildModule = None # type: typing.Optional self._buildFunction = _GetBuildFunction( self.BuildModule ) # type: typing.Optional[typing.Callable[[str], bool]] self._buildPublishingFunction = _GetBuildPublishingFunction( self.BuildModule ) # type: typing.Optional[typing.Callable[[], bool]] _mods.append(self)
def Build (self, value: typing.Tuple[typing.Union[int, str], ...]) -> None: if not isinstance(value, tuple): raise Exceptions.IncorrectTypeException(value, "Build", (tuple,)) for buildIdentifierIndex in range(len(value)): # type: int buildIdentifier = value[buildIdentifierIndex] # type: typing.Union[str, int] if not isinstance(buildIdentifier, (str, int)): raise Exceptions.IncorrectTypeException(value, "PreRelease[%s]" % buildIdentifierIndex, (str, int)) if isinstance(buildIdentifier, str): if not self.ValidStringIdentifier(buildIdentifier): raise ValueError("'PreRelease[%s]' contains a character outside what is allowed (0-9, A-Z, a-z, or -).\nValue: %s" % (buildIdentifierIndex, buildIdentifier)) self._build = value
def ValidStringIdentifier (cls, identifier: str) -> bool: """ Get whether or not a pre-release or build string identifier is valid. An identifier is invalid if it contains a character outside what is permitted (0-9, A-Z, a-z, or -). """ if not isinstance(identifier, str): raise Exceptions.IncorrectTypeException(identifier, "identifier", (str,)) if re.match(cls.StringIdentifierPattern, identifier) is None: return False return True
def IsValid (cls, versionString: str) -> bool: """ Get whether or not the input version string is valid. :param versionString: A string containing a valid or invalid version number. :type versionString: str """ if not isinstance(versionString, str): raise Exceptions.IncorrectTypeException(versionString, "versionString", (str,)) match = cls.ParsePattern.match(versionString) return bool(match)
def __init__ (self, versionString: typing.Optional[str] = None, translate: bool = False): """ A version system based on semantic versioning specification. https://semver.org/ :param versionString: A string containing a valid version. Invalid inputs will produce exceptions. Letting this be none will cause the version object to default to '0.0.0'. :type versionString: typing.Optional[str] :param translate: Whether or not we should try to translate a version number if we cannot parse it initially. :type translate: bool """ if not isinstance(versionString, str) and versionString is not None: raise Exceptions.IncorrectTypeException(versionString, "versionString", (str, None)) self.Major = 0 self.Minor = 0 self.Patch = 0 self.PreRelease = () self.Build = () if versionString is not None: self.Apply(*self.Parse(versionString, translate = translate))
def Patch (self, value: int) -> None: if not isinstance(value, int): raise Exceptions.IncorrectTypeException(value, "Patch", (int,)) self._patch = value
def Minor (self, value: int) -> None: if not isinstance(value, int): raise Exceptions.IncorrectTypeException(value, "Minor", (int,)) self._minor = value
def Translate (cls, versionString: str) -> str: """ Try to translate a version string of another type to one that is inline with the semantic versioning specification. An exception will be raised if we could not translate if to a valid format. """ if not isinstance(versionString, str): raise Exceptions.IncorrectTypeException(versionString, "versionString", (str,)) preReleaseStartIndex = versionString.find("-") # type: typing.Optional[int] preReleaseStartIndex = None if preReleaseStartIndex == -1 else preReleaseStartIndex buildStartIndex = versionString.find("+") # type: typing.Optional[int] buildStartIndex = None if buildStartIndex == -1 else buildStartIndex if buildStartIndex is not None and preReleaseStartIndex is not None: if buildStartIndex <= preReleaseStartIndex: # Pre-release identifiers cannot come after the build meta data. The hyphen we found is just part of the build meta data. preReleaseStartIndex = None if preReleaseStartIndex is not None: mainPart = versionString[0:preReleaseStartIndex] # type: str elif buildStartIndex is not None: mainPart = versionString[0:buildStartIndex] # type: str else: mainPart = versionString if not mainPart: raise ValueError("Could not find at least a major version number in '%s'." % versionString) preReleasePart = versionString[preReleaseStartIndex + 1:buildStartIndex] if preReleaseStartIndex is not None else "" # type: str buildPart = versionString[buildStartIndex + 1:None] if buildStartIndex is not None else "" # type: str mainPartIdentifiers = mainPart.split(".") # type: typing.List[str] if len(mainPartIdentifiers) > 3: # Too many identifiers in the main part, these will be booted to the front of the build meta data. All semantic version numbers can only have major, minor, and patch numbers in their main sections. mainPartExtraIdentifiers = mainPartIdentifiers[3:] if buildPart: buildPart = ".".join(mainPartExtraIdentifiers) + "." + buildPart else: buildPart = ".".join(mainPartExtraIdentifiers) mainPartIdentifiers = mainPartIdentifiers[:3] assert len(mainPartIdentifiers) == 3 elif len(mainPartIdentifiers) < 3: # Too few identifiers in the main part, we need to add at least one. All semantic version numbers must have major, minor, and patch numbers. mainPartMissingIdentifiers = 3 - len(mainPartIdentifiers) # type: int for _ in range(mainPartMissingIdentifiers): mainPartIdentifiers.append("0") assert len(mainPartIdentifiers) == 3 mainPart = ".".join(mainPartIdentifiers) buildPart = buildPart.replace("+", ".") # Replace extra plus signs in the build meta data part. More than one plus sign in a version string will cause errors. translatedVersionString = "" if mainPart: translatedVersionString += mainPart if preReleasePart: translatedVersionString += "-" + preReleasePart if buildPart: translatedVersionString += "+" + buildPart if not cls.IsValid(translatedVersionString): raise ValueError("Could not translate '%s' to a valid version number." % versionString) return translatedVersionString
def Parse (cls, versionString: str, translate: bool = False) -> typing.Tuple[int, int, int, typing.Tuple[typing.Union[int, str], ...], typing.Tuple[typing.Union[int, str], ...]]: """ Parse a version string to get its major, minor, patch, pre-release and build metadata values placed in a tuple in that order. :param versionString: A string containing a valid version. Invalid inputs will produce exceptions. :type: str :param translate: Whether or not we should try to translate a version number if we cannot parse it initially. :type translate: bool """ if not isinstance(versionString, str): raise Exceptions.IncorrectTypeException(versionString, "versionString", (str,)) match = cls.ParsePattern.match(versionString) # type: typing.Optional[typing.Match] if translate: try: translatedVersionString = cls.Translate(versionString) except Exception as e: raise ValueError("Could not parse or translate the version string '%s'." % versionString) from e match = cls.ParsePattern.match(translatedVersionString) # type: typing.Optional[typing.Match] if not match: raise ValueError("Could not parse or translate the version string '%s'." % versionString) else: if not match: raise ValueError("Could not parse the version string '%s'." % versionString) (majorString, minorString, patchString, preReleaseString, buildString) = match.groups() # type: str major = int(majorString) # type: int minor = int(minorString) # type: int patch = int(patchString) # type: int if preReleaseString: preReleaseIdentifiers = preReleaseString.split(".") # type: typing.List[str] preRelease = () # type: typing.Tuple[typing.Union[int, str], ...] for preReleaseIdentifier in preReleaseIdentifiers: # type: str try: preRelease += (int(preReleaseIdentifier),) continue except: pass preRelease += (preReleaseIdentifier,) else: preRelease = () # type: typing.Tuple[typing.Union[int, str], ...] if buildString: buildIdentifiers = buildString.split(".") # type: typing.List[str] build = () # type: typing.Tuple[typing.Union[int, str], ...] for buildIdentifier in buildIdentifiers: # type: str try: build += (int(buildIdentifier),) continue except: pass build += (buildIdentifier,) else: build = () # type: typing.Tuple[typing.Union[int, str], ...] return major, minor, patch, preRelease, build