Merge ~racb/ubuntu-sponsoring:git-ubuntu-applied-branches into ubuntu-sponsoring:main

Proposed by Robie Basak
Status: Needs review
Proposed branch: ~racb/ubuntu-sponsoring:git-ubuntu-applied-branches
Merge into: ubuntu-sponsoring:main
Diff against target: 160 lines (+75/-9)
4 files modified
debian/control (+1/-0)
setup.py (+4/-1)
ubuntu_sponsoring/sponsors_page.py (+13/-8)
ubuntu_sponsoring/sponsors_page_test.py (+57/-0)
Reviewer Review Type Date Requested Status
Benjamin Drung Pending
Review via email: mp+469860@code.launchpad.net

Description of the change

This branch does two things:

1) It displays git-ubuntu applied branches in the sponsorship report, was my intent when I started the branch. To make this easier to develop I added unit tests. To make the unit tests work I had to rearrange the code so that it's all in a module that can be found by pytest, using entry_points= instead of scripts= in setup.py, and arrange for the tests to run on package build.

2) There's a separate bug that stopped the sponsorship report from working over the weekend due to an escaping issue. I fixed this in the final commit as I discovered it during testing.

If you want you can cherry-pick just the latter issue. I could have submitted it as a separate MP, but that's painful because I have moved the script itself, and it seems likely this will result in conflicts to resolve if cherry-picking or trying to merge the two changes separately. If we merge them together then that will save that work.

To post a comment you must log in.
Revision history for this message
Robie Basak (racb) wrote :

You might want to review this with --find-renames

Revision history for this message
Benjamin Drung (bdrung) wrote :

I cherry-picked the top commit to fix the generation failure. I'll review the remaining commit tomorrow.

From a quick glance: "Make sponsors-page a proper entry point" could be the first commit to avoid creating a symlink to then remove that later again.

Revision history for this message
Robie Basak (racb) wrote :

> From a quick glance: "Make sponsors-page a proper entry point" could be the first commit to avoid creating a symlink to then remove that later again.

Agreed. But I didn't know or expect that I'd need to fix that before I tried to get the tests to run as part of the build, and they did run correctly from the development tree. I didn't think it was worth trying to rebase everything through the rename to reorder it, given that the commits are correct as-is and the state of the source tree at the end is also the ideal result.

I was about to rejiggle this for you but I see that you've also moved to pyproject.toml now so it needs redoing differently. That's fine but is it OK if I leave it to you then please to refactor as you wish?

Revision history for this message
Robie Basak (racb) wrote :

> The README.md needs an update.

I suggest just:

-./sponsors-page
+python3 ubuntu_sponsoring/sponsors_page.py

Unmerged commits

5fed1c2... by Robie Basak

Fix escaping in string substitutions

re.sub() is defined to accept and interpret escapes in the replacement
string. This is not what we want. Currently r'\e' is present in the bug
title of a sponsorship request, and this causes the report generation to
fail with an exception since that is not a valid escape.

Instead, use plain str.replace(), which does not do such substitutions.
There is no need to use regular expressions to find simple string
substrings, and this avoids the issue since str.replace() is not defined
to do any interpretation of the replacement string.

c4f179d... by Robie Basak

Run tests at build time

ffc2745... by Robie Basak

Make sponsors-page a proper entry point

I'd like to be able to test functions inside sponsors-page, and that's
difficult with it being a standalone script at the top level.

If we use the entry point functionality of setuptools, then it will
manage the top-level script for us automatically, and then all the
useful code can be with a function inside the ubuntu_sponsoring module,
making all the code we ship testable.

Then we can drop the sponsors_page.py symlink, too.

7838b0f... by Robie Basak

Display MPs against git-ubuntu applied branches

I noticed that the sponsoring page wasn't showing an MP which
(incorrectly) targetted applied/ubuntu/noble-devel. But we should
display these regardless.

694a0f6... by Robie Basak

Add tests for get_git_ubuntu_target_series()

3b99311... by Robie Basak

Add sponsors_page.py symlink

This allows us to import the main script for testing purposes.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/control b/debian/control
2index 1e0ff47..ff5c721 100644
3--- a/debian/control
4+++ b/debian/control
5@@ -10,6 +10,7 @@ Build-Depends: debhelper-compat (= 12),
6 python3-cachetools,
7 python3-launchpadlib,
8 python3-lxml,
9+ python3-pytest,
10 python3-setuptools
11 Testsuite: autopkgtest-pkg-python
12 Standards-Version: 4.6.2
13diff --git a/setup.py b/setup.py
14index 94a58da..8c5fef7 100644
15--- a/setup.py
16+++ b/setup.py
17@@ -9,7 +9,9 @@ setup(
18 author="Benjamin Drung <bdrung@ubuntu.com>",
19 requires=["bs4", "cachetools", "launchpadlib", "lxml"],
20 packages=["ubuntu_sponsoring"],
21- scripts=["sponsors-page"],
22+ entry_points={'console_scripts': [
23+ 'sponsors-page=ubuntu_sponsoring.sponsors_page:main',
24+ ]},
25 data_files=[
26 (
27 "share/ubuntu-sponsoring",
28@@ -24,4 +26,5 @@ setup(
29 ],
30 )
31 ],
32+ tests_require=['pytest'],
33 )
34diff --git a/sponsors-page b/ubuntu_sponsoring/sponsors_page.py
35similarity index 93%
36rename from sponsors-page
37rename to ubuntu_sponsoring/sponsors_page.py
38index 482104b..a940de0 100755
39--- a/sponsors-page
40+++ b/ubuntu_sponsoring/sponsors_page.py
41@@ -15,7 +15,6 @@ import logging
42 import operator
43 import os
44 import pathlib
45-import re
46 import shutil
47 import sys
48 from typing import Collection, Iterable, MutableMapping, Optional, Union
49@@ -57,7 +56,7 @@ LP_UBUNTU_DISTRIBUTION = "https://api.launchpad.net/devel/ubuntu"
50 LOG_FORMAT = "%(asctime)-15s %(levelname)s: %(message)s"
51 __script_name__ = os.path.basename(sys.argv[0]) if __name__ == "__main__" else __name__
52
53-if __file__.startswith("/usr/bin"):
54+if __file__.startswith("/usr/lib"):
55 DATA_DIR = pathlib.Path("/usr/share/ubuntu-sponsoring")
56 else:
57 DATA_DIR = pathlib.Path(sys.argv[0]).parent
58@@ -88,9 +87,9 @@ def htmlify_name(person, package, devs, distribution):
59 def classify_name(prefix, name):
60 name = name.upper()
61 if prefix == "status":
62- name = re.sub(" ", "", name)
63+ name = name.replace(" ", "")
64 else:
65- name = re.sub(" ", "_", name)
66+ name = name.replace(" ", "_")
67 return prefix + name
68
69
70@@ -574,9 +573,15 @@ def get_branches(lp, distribution, team):
71
72
73 def get_git_ubuntu_target_series(ubuntu, target_git_path):
74- if target_git_path.startswith("refs/heads/ubuntu/"):
75- effective_target_git_path = target_git_path
76- elif target_git_path == "refs/heads/debian/sid":
77+ if target_git_path.startswith("refs/heads/applied/"):
78+ unapplied_target_git_path = (
79+ "refs/heads/" + target_git_path.removeprefix("refs/heads/applied/")
80+ )
81+ else:
82+ unapplied_target_git_path = target_git_path
83+ if unapplied_target_git_path.startswith("refs/heads/ubuntu/"):
84+ effective_target_git_path = unapplied_target_git_path
85+ elif unapplied_target_git_path == "refs/heads/debian/sid":
86 # We use "debian/sid" for package merge MPs. LP: 1976112
87 effective_target_git_path = "refs/heads/ubuntu/devel"
88 else:
89@@ -772,7 +777,7 @@ def generate_page(
90 template = DATA_DIR / "template.html"
91 html_report = template.read_text(encoding="utf-8")
92 for pattern, substitution in subst.items():
93- html_report = re.sub("@" + pattern + "@", str(substitution), html_report)
94+ html_report = html_report.replace("@" + pattern + "@", str(substitution))
95
96 if os.path.exists(filename):
97 os.remove(filename)
98diff --git a/ubuntu_sponsoring/sponsors_page_test.py b/ubuntu_sponsoring/sponsors_page_test.py
99new file mode 100644
100index 0000000..48b2e69
101--- /dev/null
102+++ b/ubuntu_sponsoring/sponsors_page_test.py
103@@ -0,0 +1,57 @@
104+import unittest.mock
105+
106+import pytest
107+
108+import ubuntu_sponsoring.sponsors_page as target
109+
110+
111+@pytest.mark.parametrize(
112+ ["current_series", "target_git_path", "expected_result"],
113+ [
114+ ("noble", "refs/heads/ubuntu/noble", "noble"),
115+ ("noble", "refs/heads/ubuntu/noble-devel", "noble"),
116+ ("noble", "refs/heads/ubuntu/jammy-devel", "jammy"),
117+ ("noble", "refs/heads/ubuntu/noble-proposed", "noble"),
118+ ("noble", "refs/heads/ubuntu/noble-updates", "noble"),
119+ ("noble", "refs/heads/ubuntu/devel", "noble"),
120+ ("noble", "refs/heads/debian/sid", "noble"),
121+ ("noble", "refs/heads/applied/ubuntu/devel", "noble"),
122+ ("noble", "refs/heads/applied/ubuntu/noble-devel", "noble"),
123+ ("noble", "refs/heads/applied/ubuntu/jammy-devel", "jammy"),
124+ ],
125+)
126+def test_get_git_ubuntu_target_series(
127+ current_series, target_git_path, expected_result
128+):
129+ # 'name' is special so we cannot use __init__ **kwarg since that
130+ # behaviour would be different.
131+ current_series_mock = unittest.mock.Mock()
132+ current_series_mock.configure_mock(name=current_series)
133+ assert (
134+ target.get_git_ubuntu_target_series(
135+ unittest.mock.Mock(current_series=current_series_mock),
136+ target_git_path,
137+ )
138+ == expected_result
139+ )
140+
141+
142+@pytest.mark.parametrize(
143+ ["current_series", "target_git_path", "expected_exception"],
144+ [
145+ ("noble", "refs/heads/debian/bullseye", ValueError),
146+ ("noble", "refs/heads/other", ValueError),
147+ ],
148+)
149+def test_get_git_ubuntu_target_series_exceptions(
150+ current_series, target_git_path, expected_exception
151+):
152+ # 'name' is special so we cannot use __init__ **kwarg since that
153+ # behaviour would be different.
154+ current_series_mock = unittest.mock.Mock()
155+ current_series_mock.configure_mock(name=current_series)
156+ with pytest.raises(expected_exception):
157+ target.get_git_ubuntu_target_series(
158+ unittest.mock.Mock(current_series=current_series_mock),
159+ target_git_path,
160+ )

Subscribers

People subscribed via source and target branches