]> git.mxchange.org Git - fba.git/blob - fba/helpers/version.py
Continued:
[fba.git] / fba / helpers / version.py
1 # Copyright (C) 2023 Free Software Foundation
2 #
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.
7 #
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.
12 #
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/>.
15
16 import logging
17 import re
18
19 logging.basicConfig(level=logging.INFO)
20 logger = logging.getLogger(__name__)
21
22 # Pattern instance for version numbers
23 patterns = [
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}$"),
32 ]
33
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)
38         return software
39
40     temp = software
41     if ";" in software:
42         temp = software.split(";")[0]
43     elif "," in software:
44         temp = software.split(",")[0]
45     elif " - " in software:
46         temp = software.split(" - ")[0]
47
48     logger.debug("software='%s'", software)
49     version = None
50     if " " in software:
51         version = temp.split(" ")[-1]
52     elif "/" in software:
53         version = temp.split("/")[-1]
54     elif "-" in software:
55         version = temp.split("-")[-1]
56     else:
57         logger.debug("Was not able to find common seperator, returning untouched software='%s' - EXIT!", software)
58         return software
59
60     match = None
61     logger.debug("Checking %d patterns ...", len(patterns))
62     for pattern in patterns:
63         # Run match()
64         match = pattern.match(version)
65
66         logger.debug("match[]='%s'", type(match))
67         if isinstance(match, re.Match):
68             logger.debug("version='%s' is matching pattern='%s'", version, pattern)
69             break
70
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)
74         return software
75
76     logger.debug("Found valid version number: '%s', removing it ...", version)
77     end = len(temp) - len(version) - 1
78
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")
84
85     logger.debug("software='%s' - EXIT!", software)
86     return software
87
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'")
92     elif software == "":
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)
96         return software
97
98     start = software.find("powered by ")
99     logger.debug("start[%s]=%d", type(start), start)
100
101     software = software[start + 11:].strip()
102     logger.debug("software='%s'", software)
103
104     if " - " in software:
105         software = strip_until(software, " - ")
106
107     logger.debug("software='%s' - EXIT!", software)
108     return software
109
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'")
114     elif software == "":
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)
118         return software
119
120     end = software.find("hosted on ")
121     logger.debug("end[%s]=%d", type(end), end)
122
123     software = software[0:end].strip()
124     logger.debug("software[%s]='%s'", type(software), software)
125
126     if " - " in software:
127         software = strip_until(software, " - ")
128
129     logger.debug("software='%s' - EXIT!", software)
130     return software
131
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'")
136     elif software == "":
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'")
140     elif until == "":
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)
144         return software
145
146     # Next, strip until part
147     end = software.find(until)
148
149     logger.debug("end[%s]=%d", type(end), end)
150     if end > 0:
151         software = software[0:end].strip()
152
153     logger.debug("software='%s' - EXIT!", software)
154     return software