1 # Copyright (C) 2023 Free Software Foundation
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License as published
5 # by the Free Software Foundation, either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU Affero General Public License for more details.
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <https://www.gnu.org/licenses/>.
19 logging.basicConfig(level=logging.INFO)
20 logger = logging.getLogger(__name__)
22 # Pattern instance for version numbers
24 # semantic version number (with v|V) prefix)
25 re.compile(r"^(?P<version>v|V{0,1})(\.{0,1})(?P<major>0|[1-9]\d*)\.(?P<minor>0+|[1-9]\d*)(\.(?P<patch>0+|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)?$"),
26 # non-sematic, e.g. 1.2.3.4
27 re.compile(r"^(?P<version>v|V{0,1})(\.{0,1})(?P<major>0|[1-9]\d*)\.(?P<minor>0+|[1-9]\d*)(\.(?P<patch>0+|[1-9]\d*)(\.(?P<subpatch>0|[1-9]\d*))?)$"),
28 # non-sematic, e.g. 2023-05[-dev]
29 re.compile(r"^(?P<year>[1-9]{1}[0-9]{3})\.(?P<month>[0-9]{2})(-dev){0,1}$"),
30 # non-semantic, e.g. abcdef0
31 re.compile("^[a-f0-9]{7}$"),
34 def remove(software: str) -> str:
35 logger.debug("software='%s' - CALLED!", software)
36 if "." not in software and " " not in software:
37 logger.warning("software='%s' does not contain a version number.", software)
42 temp = software.split(";")[0]
44 temp = software.split(",")[0]
45 elif " - " in software:
46 temp = software.split(" - ")[0]
48 logger.debug("software='%s'", software)
51 version = temp.split(" ")[-1]
53 version = temp.split("/")[-1]
55 version = temp.split("-")[-1]
57 logger.debug("Was not able to find common seperator, returning untouched software='%s' - EXIT!", software)
61 logger.debug("Checking %d patterns ...", len(patterns))
62 for pattern in patterns:
64 match = pattern.match(version)
66 logger.debug("match[]='%s'", type(match))
67 if isinstance(match, re.Match):
68 logger.debug("version='%s' is matching pattern='%s'", version, pattern)
71 logger.debug("version[%s]='%s',match='%s'", type(version), version, match)
72 if not isinstance(match, re.Match):
73 logger.warning("version='%s' does not match regex, leaving software='%s' untouched.", version, software)
76 logger.debug("Found valid version number: '%s', removing it ...", version)
77 end = len(temp) - len(version) - 1
79 logger.debug("end[%s]='%s'", type(end), end)
80 software = temp[0:end].strip()
81 if " version" in software:
82 logger.debug("software='%s' contains word ' version'", software)
83 software = strip_until(software, " version")
85 logger.debug("software='%s' - EXIT!", software)
88 def strip_powered_by(software: str) -> str:
89 logger.debug("software='%s' - CALLED!", software)
90 if not isinstance(software, str):
91 raise ValueError(f"Parameter software[]='{type(software)}' is not of type 'str'")
93 raise ValueError("Parameter 'software' is empty")
94 elif "powered by" not in software:
95 logger.warning("Cannot find 'powered by' in software='%s'!", software)
98 start = software.find("powered by ")
99 logger.debug("start[%s]=%d", type(start), start)
101 software = software[start + 11:].strip()
102 logger.debug("software='%s'", software)
104 if " - " in software:
105 software = strip_until(software, " - ")
107 logger.debug("software='%s' - EXIT!", software)
110 def strip_hosted_on(software: str) -> str:
111 logger.debug("software='%s' - CALLED!", software)
112 if not isinstance(software, str):
113 raise ValueError(f"Parameter software[]='{type(software)}' is not of type 'str'")
115 raise ValueError("Parameter 'software' is empty")
116 elif "hosted on" not in software:
117 logger.warning("Cannot find 'hosted on' in sofware='%s'!", software)
120 end = software.find("hosted on ")
121 logger.debug("end[%s]=%d", type(end), end)
123 software = software[0:end].strip()
124 logger.debug("software[%s]='%s'", type(software), software)
126 if " - " in software:
127 software = strip_until(software, " - ")
129 logger.debug("software='%s' - EXIT!", software)
132 def strip_until(software: str, until: str) -> str:
133 logger.debug("software='%s',until='%s' - CALLED!", software, until)
134 if not isinstance(software, str):
135 raise ValueError(f"Parameter software[]='{type(software)}' is not of type 'str'")
137 raise ValueError("Parameter 'software' is empty")
138 elif not isinstance(until, str):
139 raise ValueError(f"Parameter until[]='{type(until)}' is not of type 'str'")
141 raise ValueError("Parameter 'until' is empty")
142 elif not until in software:
143 logger.warning("Cannot find until='%s' in software='%s'!", until, software)
146 # Next, strip until part
147 end = software.find(until)
149 logger.debug("end[%s]=%d", type(end), end)
151 software = software[0:end].strip()
153 logger.debug("software='%s' - EXIT!", software)