Skip to content

Commit f1b8883

Browse files
committed
post-simplification of diff.py after Wheelhouse addition
1 parent b5a339a commit f1b8883

File tree

1 file changed

+78
-112
lines changed

1 file changed

+78
-112
lines changed

diff.py

Lines changed: 78 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -17,120 +17,94 @@
1717
assert CHANGELOGS_DIR.is_dir()
1818

1919
class Package:
20-
# SourceForge Wiki syntax:
21-
PATTERN = r"\[([a-zA-Z\-\:\/\.\_0-9]*)\]\(([^\]\ ]*)\) \| ([^\|]*) \| ([^\|]*)"
22-
# Google Code Wiki syntax:
23-
PATTERN_OLD = r"\[([a-zA-Z\-\:\/\.\_0-9]*) ([^\]\ ]*)\] \| ([^\|]*) \| ([^\|]*)"
20+
PATTERNS = [
21+
r"\[([\w\-\:\/\.\_]+)\]\(([^)]+)\) \| ([^\|]*) \| ([^\|]*)", # SourceForge
22+
r"\[([\w\-\:\/\.\_]+) ([^\]\ ]+)\] \| ([^\|]*) \| ([^\|]*)" # Google Code
23+
]
2424

25-
def __init__(self):
26-
self.name = self.version = self.description = self.url = None
27-
28-
def __str__(self):
29-
return f"{self.name} {self.version}\r\n{self.description}\r\nWebsite: {self.url}"
25+
def __init__(self, text=None):
26+
self.name = self.url = self.version = self.description = None
27+
if text:
28+
self.from_text(text)
3029

3130
def from_text(self, text):
32-
match = re.match(self.PATTERN_OLD, text) or re.match(self.PATTERN, text)
33-
if not match:
34-
raise ValueError("Text does not match expected pattern: "+ text)
35-
self.name, self.url, self.version, self.description = match.groups()
31+
for pattern in self.PATTERNS:
32+
match = re.match(pattern, text)
33+
if match:
34+
self.name, self.url, self.version, self.description = match.groups()
35+
return
36+
raise ValueError(f"Unrecognized package line format: {text}")
3637

3738
def to_wiki(self):
3839
return f" * [{self.name}]({self.url}) {self.version} ({self.description})\r\n"
3940

4041
def upgrade_wiki(self, other):
41-
assert self.name.replace("-", "_").lower() == other.name.replace("-", "_").lower()
4242
return f" * [{self.name}]({self.url}) {other.version}{self.version} ({self.description})\r\n"
4343

4444
class PackageIndex:
45-
WINPYTHON_PATTERN = r"\#\# WinPython\-*[0-9b-t]* ([0-9\.a-zA-Z]*)"
46-
TOOLS_LINE = "### Tools"
47-
PYTHON_PACKAGES_LINE = "### Python packages"
48-
WHEELHOUSE_PACKAGES_LINE = "### WheelHouse packages"
49-
HEADER_LINE1 = "Name | Version | Description"
50-
HEADER_LINE2 = "-----|---------|------------"
45+
HEADERS = {"tools": "### Tools", "python": "### Python packages", "wheelhouse": "### WheelHouse packages"}
46+
BLANKS = ["Name | Version | Description", "-----|---------|------------", "", "<details>", "</details>"]
5147

5248
def __init__(self, version, basedir=None, flavor="", architecture=64):
5349
self.version = version
5450
self.flavor = flavor
5551
self.basedir = basedir
5652
self.architecture = architecture
57-
self.other_packages = {}
58-
self.python_packages = {}
59-
self.wheelhouse_packages = {}
60-
self.from_file(basedir)
61-
62-
def from_file(self, basedir):
63-
fname = CHANGELOGS_DIR / f"WinPython{self.flavor}-{self.architecture}bit-{self.version}.md"
64-
if not fname.exists():
65-
raise FileNotFoundError(f"Changelog file not found: {fname}")
66-
with open(fname, "r", encoding=utils.guess_encoding(fname)[0]) as fdesc:
67-
self.from_text(fdesc.read())
53+
self.packages = {"tools": {}, "python": {}, "wheelhouse": {}}
54+
self._load_index()
6855

69-
def from_text(self, text):
70-
version = re.match(self.WINPYTHON_PATTERN + self.flavor, text).groups()[0]
71-
assert version == self.version
72-
tools_flag = python_flag = wheelhouse_flag = False
56+
def _load_index(self):
57+
filename = CHANGELOGS_DIR / f"WinPython{self.flavor}-{self.architecture}bit-{self.version}.md"
58+
if not filename.exists():
59+
raise FileNotFoundError(f"Changelog not found: {filename}")
60+
61+
with open(filename, "r", encoding=utils.guess_encoding(filename)[0]) as f:
62+
self._parse_index(f.read())
63+
64+
def _parse_index(self, text):
65+
current = None
7366
for line in text.splitlines():
74-
if line:
75-
if line == self.TOOLS_LINE:
76-
tools_flag, python_flag, wheelhouse_flag = True, False, False
77-
continue
78-
elif line == self.PYTHON_PACKAGES_LINE:
79-
tools_flag, python_flag, wheelhouse_flag = False, True, False
80-
continue
81-
elif line == self.WHEELHOUSE_PACKAGES_LINE:
82-
tools_flag, python_flag, wheelhouse_flag = False, False, True
83-
continue
84-
elif line in (self.HEADER_LINE1, self.HEADER_LINE2, "<details>", "</details>"):
85-
continue
86-
if tools_flag or python_flag or wheelhouse_flag:
87-
package = Package()
88-
package.from_text(line)
89-
if tools_flag:
90-
self.other_packages[package.name] = package
91-
elif python_flag:
92-
self.python_packages[package.name] = package
93-
else:
94-
self.wheelhouse_packages[package.name] = package
95-
96-
def diff_package_dicts(old_packages, new_packages):
67+
if line in self.HEADERS.values():
68+
current = [k for k, v in self.HEADERS.items() if v == line][0]
69+
continue
70+
if line.strip() in self.BLANKS:
71+
continue
72+
if current:
73+
pkg = Package(line)
74+
self.packages[current][pkg.name] = pkg
75+
76+
def compare_packages(old, new):
9777
"""Return difference between package old and package new"""
9878

9979
# wheel replace '-' per '_' in key
100-
old = {k.replace("-", "_").lower(): v for k, v in old_packages.items()}
101-
new = {k.replace("-", "_").lower(): v for k, v in new_packages.items()}
102-
text = ""
103-
104-
if new_keys := sorted(set(new) - set(old)):
105-
text += "New packages:\r\n\r\n" + "".join(new[k].to_wiki() for k in new_keys) + "\r\n"
106-
107-
if upgraded := [new[k].upgrade_wiki(old[k]) for k in sorted(set(old) & set(new)) if old[k].version != new[k].version]:
108-
text += "Upgraded packages:\r\n\r\n" + f"{''.join(upgraded)}" + "\r\n"
109-
110-
if removed_keys := sorted(set(old) - set(new)):
111-
text += "Removed packages:\r\n\r\n" + "".join(old[k].to_wiki() for k in removed_keys) + "\r\n"
112-
return text
113-
114-
def find_closer_version(version1, basedir=None, flavor="", architecture=64):
80+
def normalize(d): return {k.replace("-", "_").lower(): v for k, v in d.items()}
81+
old, new = normalize(old), normalize(new)
82+
output = ""
83+
84+
added = [new[k].to_wiki() for k in new if k not in old]
85+
upgraded = [new[k].upgrade_wiki(old[k]) for k in new if k in old and new[k].version != old[k].version]
86+
removed = [old[k].to_wiki() for k in old if k not in new]
87+
88+
if added:
89+
output += "New packages:\r\n\r\n" + "".join(added) + "\r\n"
90+
if upgraded:
91+
output += "Upgraded packages:\r\n\r\n" + "".join(upgraded) + "\r\n"
92+
if removed:
93+
output += "Removed packages:\r\n\r\n" + "".join(removed) + "\r\n"
94+
return output
95+
96+
def find_previous_version(target_version, basedir=None, flavor="", architecture=64):
11597
"""Find version which is the closest to `version`"""
116-
builddir = Path(basedir) / f"bu{flavor}"
117-
pattern = re.compile(rf"WinPython{flavor}-{architecture}bit-([0-9\.]*)\.(txt|md)")
118-
versions = [pattern.match(name).groups()[0] for name in os.listdir(builddir) if pattern.match(name)]
119-
120-
if version1 not in versions:
121-
raise ValueError(f"Unknown version {version1}")
122-
123-
version_below = '0.0.0.0'
124-
for v in versions:
125-
if version.parse(version_below) < version.parse(v) and version.parse(v) < version.parse(version1):
126-
version_below = v
98+
build_dir = Path(basedir) / f"bu{flavor}"
99+
pattern = re.compile(rf"WinPython{flavor}-{architecture}bit-([0-9\.]+)\.(txt|md)")
100+
versions = [pattern.match(f).group(1) for f in os.listdir(build_dir) if pattern.match(f)]
101+
versions = [v for v in versions if version.parse(v) < version.parse(target_version)]
102+
return max(versions, key=version.parse, default=target_version)
127103

128-
return version_below if version_below != '0.0.0.0' else version1
104+
def compare_package_indexes(version2, version1=None, basedir=None, flavor="", flavor1=None, architecture=64):
105+
version1 = version1 or find_previous_version(version2, basedir, flavor, architecture)
106+
flavor1 = flavor1 or flavor
129107

130-
def compare_package_indexes(version2, version1=None, basedir=None, flavor="", flavor1=None,architecture=64):
131-
"""Compare two package index Wiki pages"""
132-
version1 = version1 if version1 else find_closer_version(version2, basedir, flavor, architecture)
133-
flavor1 = flavor1 if flavor1 else flavor
134108
pi1 = PackageIndex(version1, basedir, flavor1, architecture)
135109
pi2 = PackageIndex(version2, basedir, flavor, architecture)
136110

@@ -140,37 +114,29 @@ def compare_package_indexes(version2, version1=None, basedir=None, flavor="", fl
140114
"<details>\r\n\r\n"
141115
)
142116

143-
tools_text = diff_package_dicts(pi1.other_packages, pi2.other_packages)
144-
if tools_text:
145-
text += PackageIndex.TOOLS_LINE + "\r\n\r\n" + tools_text
117+
for key in PackageIndex.HEADERS:
118+
diff = compare_packages(pi1.packages[key], pi2.packages[key])
119+
if diff:
120+
text += f"{PackageIndex.HEADERS[key]}\r\n\r\n{diff}"
146121

147-
py_text = diff_package_dicts(pi1.python_packages, pi2.python_packages)
148-
if py_text:
149-
text += PackageIndex.PYTHON_PACKAGES_LINE + "\r\n\r\n" + py_text
122+
return text + "\r\n</details>\r\n* * *\r\n"
150123

151-
py_text = diff_package_dicts(pi1.wheelhouse_packages, pi2.wheelhouse_packages)
152-
if py_text:
153-
text += PackageIndex.WHEELHOUSE_PACKAGES_LINE + "\r\n\r\n" + py_text
154-
155-
text += "\r\n</details>\r\n* * *\r\n"
156-
return text
157-
158-
def _copy_all_changelogs(version, basedir, flavor="", architecture=64):
124+
def copy_changelogs(version, basedir, flavor="", architecture=64):
159125
basever = ".".join(version.split(".")[:2])
160-
pattern = re.compile(rf"WinPython{flavor}-{architecture}bit-{basever}([0-9\.]*)\.(txt|md)")
161-
for name in os.listdir(CHANGELOGS_DIR):
162-
if pattern.match(name):
163-
shutil.copyfile(CHANGELOGS_DIR / name, Path(basedir) / f"bu{flavor}" / name)
126+
pattern = re.compile(rf"WinPython{flavor}-{architecture}bit-{basever}[0-9\.]*\.(txt|md)")
127+
dest = Path(basedir) / f"bu{flavor}"
128+
for fname in os.listdir(CHANGELOGS_DIR):
129+
if pattern.match(fname):
130+
shutil.copyfile(CHANGELOGS_DIR / fname, dest / fname)
164131

165132
def write_changelog(version2, version1=None, basedir=None, flavor="", architecture=64):
166133
"""Write changelog between version1 and version2 of WinPython"""
167-
_copy_all_changelogs(version2, basedir, flavor, architecture)
134+
copy_changelogs(version2, basedir, flavor, architecture)
168135
print("comparing_package_indexes", version2, basedir, flavor, architecture)
169-
changelog_text = compare_package_indexes(version2, version1, basedir, flavor, architecture=architecture)
136+
changelog = compare_package_indexes(version2, version1, basedir, flavor, architecture=architecture)
170137
output_file = Path(basedir) / f"bu{flavor}" / f"WinPython{flavor}-{architecture}bit-{version2}_History.md"
171-
172-
with open(output_file, "w", encoding="utf-8") as fdesc:
173-
fdesc.write(changelog_text)
138+
with open(output_file, "w", encoding="utf-8") as f:
139+
f.write(changelog)
174140
# Copy to winpython/changelogs
175141
shutil.copyfile(output_file, CHANGELOGS_DIR / output_file.name)
176142

0 commit comments

Comments
 (0)