Skip to content

Commit 41918fd

Browse files
committed
Enable typeguard during build time and tests, fix issues found
It is also possible to use typeguard in osc-wrapper.py by setting OSC_TYPEGUARD=1.
1 parent d2ed088 commit 41918fd

11 files changed

Lines changed: 138 additions & 68 deletions

File tree

.github/workflows/tests.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ jobs:
134134
sudo apt-get -y --no-install-recommends install git python3-behave diffstat diffutils python3 python3-cryptography python3-pip python3-rpm python3-ruamel.yaml python3-setuptools python3-urllib3 obs-build obs-service-set-version
135135
# obs-scm-bridge is not available as a package at the moment, install it from github
136136
sudo pip3 config set global.break-system-packages 1
137+
sudo pip3 install typeguard
137138
sudo pip3 install git+https://github.com/openSUSE/obs-scm-bridge
138139
sudo chmod a+x /usr/local/lib/*/*/obs_scm_bridge
139140
sudo mkdir -p /usr/lib/obs/service
@@ -149,4 +150,4 @@ jobs:
149150
- name: "Run tests"
150151
run: |
151152
cd behave
152-
behave -Dosc=../osc-wrapper.py -Dgit-obs=../git-obs.py -Dpodman_max_containers=2
153+
OSC_TYPEGUARD=1 behave -Dosc=../osc-wrapper.py -Dgit-obs=../git-obs.py -Dpodman_max_containers=2

contrib/osc.spec

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@
3030
%bcond_with fdupes
3131
%endif
3232

33+
# use typeguard during build on distros where typeguard is available
34+
%if (0%{?suse_version} > 1500 || 0%{?fedora} >= 37)
35+
%bcond_without typeguard
36+
%else
37+
%bcond_with typeguard
38+
%endif
39+
3340
# the macro exists only on openSUSE based distros
3441
%if %{undefined python3_fix_shebang}
3542
%define python3_fix_shebang %nil
@@ -76,6 +83,9 @@ BuildRequires: %{use_python_pkg}-cryptography
7683
BuildRequires: %{use_python_pkg}-devel >= 3.6
7784
BuildRequires: %{use_python_pkg}-rpm
7885
BuildRequires: %{use_python_pkg}-setuptools
86+
%if %{with typeguard}
87+
BuildRequires: %{use_python_pkg}-typeguard
88+
%endif
7989
BuildRequires: %{use_python_pkg}-urllib3
8090
BuildRequires: %{ruamel_yaml_pkg}
8191
BuildRequires: diffstat

osc-wrapper.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,29 @@
44
This wrapper allows osc to be called from the source directory during development.
55
"""
66

7+
8+
import os
9+
10+
11+
USE_TYPEGUARD = os.environ.get("OSC_TYPEGUARD", "1").lower() in ("1", "true", "on")
12+
13+
if USE_TYPEGUARD:
14+
try:
15+
from typeguard import install_import_hook
16+
except ImportError:
17+
install_import_hook = None
18+
19+
if install_import_hook is None:
20+
try:
21+
from typeguard.importhook import install_import_hook
22+
except ImportError:
23+
install_import_hook = None
24+
25+
if install_import_hook:
26+
# install typeguard import hook only if available
27+
install_import_hook("osc")
28+
29+
730
import osc.babysitter
831

932
osc.babysitter.main()

osc/commandline.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from pathlib import Path
2525
from tempfile import NamedTemporaryFile
2626
from typing import List
27+
from typing import Optional
2728
from urllib.parse import urlsplit
2829
from urllib.error import HTTPError
2930

@@ -316,10 +317,10 @@ def pop_args(
316317
args,
317318
arg1_name: str = None,
318319
arg1_is_optional: bool = False,
319-
arg1_default: str = None,
320+
arg1_default: Optional[str] = None,
320321
arg2_name: str = None,
321322
arg2_is_optional: bool = False,
322-
arg2_default: str = None,
323+
arg2_default: Optional[str] = None,
323324
):
324325
"""
325326
Pop 2 arguments from `args`.
@@ -391,9 +392,9 @@ def pop_args(
391392
def pop_project_package_from_args(
392393
args: List[str],
393394
project_is_optional: bool = False,
394-
default_project: str = None,
395+
default_project: Optional[str] = None,
395396
package_is_optional: bool = False,
396-
default_package: str = None,
397+
default_package: Optional[str] = None,
397398
):
398399
"""
399400
Pop project and package from given `args`.
@@ -464,9 +465,9 @@ def pop_project_package_from_args(
464465
def pop_repository_arch_from_args(
465466
args: List[str],
466467
repository_is_optional: bool = False,
467-
default_repository: str = None,
468+
default_repository: Optional[str] = None,
468469
arch_is_optional: bool = False,
469-
default_arch: str = None,
470+
default_arch: Optional[str] = None,
470471
):
471472
"""
472473
Pop repository and arch from given `args`.
@@ -503,13 +504,13 @@ def pop_repository_arch_from_args(
503504
def pop_project_package_repository_arch_from_args(
504505
args: List[str],
505506
project_is_optional: bool = False,
506-
default_project: str = None,
507+
default_project: Optional[str] = None,
507508
package_is_optional: bool = False,
508-
default_package: str = None,
509+
default_package: Optional[str] = None,
509510
repository_is_optional: bool = False,
510-
default_repository: str = None,
511+
default_repository: Optional[str] = None,
511512
arch_is_optional: bool = False,
512-
default_arch: str = None,
513+
default_arch: Optional[str] = None,
513514
):
514515
"""
515516
Pop project, package, repository and arch from given `args`.
@@ -589,13 +590,13 @@ def pop_project_package_repository_arch_from_args(
589590
def pop_project_package_targetproject_targetpackage_from_args(
590591
args: List[str],
591592
project_is_optional: bool = False,
592-
default_project: str = None,
593+
default_project: Optional[str] = None,
593594
package_is_optional: bool = False,
594-
default_package: str = None,
595+
default_package: Optional[str] = None,
595596
target_project_is_optional: bool = False,
596-
default_target_project: str = None,
597+
default_target_project: Optional[str] = None,
597598
target_package_is_optional: bool = False,
598-
default_target_package: str = None,
599+
default_target_package: Optional[str] = None,
599600
):
600601
"""
601602
Pop project, package, target project and target package from given `args`.
@@ -4914,6 +4915,8 @@ def do_rdiff(self, subcmd, opts, *args):
49144915
rev2 = -rev - 1
49154916
else:
49164917
return
4918+
rev1 = str(rev1)
4919+
rev2 = str(rev2)
49174920
except:
49184921
print(f'Revision \'{opts.change}\' not an integer', file=sys.stderr)
49194922
return

osc/core.py

Lines changed: 48 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,7 +1325,7 @@ def show_package_trigger_reason(apiurl: str, prj: str, pac: str, repo: str, arch
13251325
raise
13261326

13271327

1328-
def show_package_meta(apiurl: str, prj: str, pac: str, meta=False, blame=None):
1328+
def show_package_meta(apiurl: str, prj: str, pac: str, meta=False, blame=None) -> List[bytes]:
13291329
query: Dict[str, Union[str, int]] = {}
13301330
if meta:
13311331
query['meta'] = 1
@@ -2320,7 +2320,7 @@ def get_request_collection(
23202320
package=None,
23212321
states=None,
23222322
review_states=None,
2323-
types: List[str] = None,
2323+
types: Optional[List[str]] = None,
23242324
ids=None,
23252325
withfullhistory=False
23262326
):
@@ -2863,20 +2863,20 @@ def get_source_file_diff(dir, filename, rev, oldfilename=None, olddir=None, orig
28632863

28642864
def server_diff(
28652865
apiurl: str,
2866-
old_project: str,
2867-
old_package: str,
2868-
old_revision: str,
2866+
old_project: Optional[str],
2867+
old_package: Optional[str],
2868+
old_revision: Optional[str],
28692869
new_project: str,
28702870
new_package: str,
2871-
new_revision: str,
2871+
new_revision: Optional[str],
28722872
unified=False,
28732873
missingok=False,
28742874
meta=False,
28752875
expand=True,
28762876
onlyissues=False,
28772877
full=True,
28782878
xml=False,
2879-
files: list = None,
2879+
files: Optional[list] = None,
28802880
):
28812881
query: Dict[str, Union[str, int]] = {"cmd": "diff"}
28822882
if expand:
@@ -2929,19 +2929,19 @@ def server_diff(
29292929

29302930
def server_diff_noex(
29312931
apiurl: str,
2932-
old_project: str,
2933-
old_package: str,
2934-
old_revision: str,
2932+
old_project: Optional[str],
2933+
old_package: Optional[str],
2934+
old_revision: Optional[str],
29352935
new_project: str,
29362936
new_package: str,
2937-
new_revision: str,
2937+
new_revision: Optional[str],
29382938
unified=False,
29392939
missingok=False,
29402940
meta=False,
29412941
expand=True,
29422942
onlyissues=False,
29432943
xml=False,
2944-
files: list = None,
2944+
files: Optional[list] = None,
29452945
):
29462946
try:
29472947
return server_diff(apiurl,
@@ -3096,7 +3096,7 @@ def checkout_package(
30963096
pathname=None,
30973097
prj_obj=None,
30983098
expand_link=False,
3099-
prj_dir: Path=None,
3099+
prj_dir: Optional[Path] = None,
31003100
server_service_files=None,
31013101
service_files=None,
31023102
native_obs_package=False,
@@ -3214,9 +3214,9 @@ def checkout_package(
32143214

32153215

32163216
def replace_pkg_meta(
3217-
pkgmeta, new_name: str, new_prj: str, keep_maintainers=False, dst_userid=None, keep_develproject=False,
3217+
pkgmeta: List[bytes], new_name: str, new_prj: str, keep_maintainers=False, dst_userid=None, keep_develproject=False,
32183218
keep_lock: bool = False, keep_scmsync: bool = True,
3219-
):
3219+
) -> str:
32203220
"""
32213221
update pkgmeta with new new_name and new_prj and set calling user as the
32223222
only maintainer (unless keep_maintainers is set). Additionally remove the
@@ -3450,7 +3450,7 @@ def aggregate_pac(
34503450

34513451
if meta_change:
34523452
src_meta = show_package_meta(apiurl, src_project, src_package_meta)
3453-
dst_meta = replace_pkg_meta(src_meta, dst_package_meta, dst_project)
3453+
dst_meta = replace_pkg_meta(src_meta, dst_package_meta, dst_project).split("\n")
34543454
meta_change = True
34553455

34563456
if disable_publish:
@@ -3808,7 +3808,7 @@ def copy_pac(
38083808
return 'Done.'
38093809

38103810

3811-
def lock(apiurl: str, project: str, package: str, msg: str = None):
3811+
def lock(apiurl: str, project: str, package: str, msg: Optional[str] = None):
38123812
url_path = ["source", project]
38133813
if package:
38143814
url_path += [package]
@@ -4756,25 +4756,26 @@ def get_commitlog(
47564756
# revision is srcmd5
47574757
revision_list = [i for i in revision_list if i.srcmd5 == revision]
47584758
else:
4759-
revision = int(revision)
4759+
assert revision is not None
4760+
revision_int = int(revision)
47604761
if revision_is_empty(revision_upper):
4761-
revision_list = [i for i in revision_list if i.rev == revision]
4762+
revision_list = [i for i in revision_list if i.rev == revision_int]
47624763
else:
4763-
revision_upper = int(revision_upper)
4764-
revision_list = [i for i in revision_list if i.rev <= revision_upper and i.rev >= revision]
4764+
revision_upper_int = int(revision_upper)
4765+
revision_list = [i for i in revision_list if i.rev <= revision_upper_int and i.rev >= revision_int]
47654766

47664767
if format == "csv":
47674768
f = io.StringIO()
47684769
writer = csv.writer(f, dialect="unix")
4769-
for revision in reversed(revision_list):
4770+
for i in reversed(revision_list):
47704771
writer.writerow(
47714772
(
4772-
revision.rev,
4773-
revision.user,
4774-
revision.get_time_str(),
4775-
revision.srcmd5,
4776-
revision.comment,
4777-
revision.requestid,
4773+
i.rev,
4774+
i.user,
4775+
i.get_time_str(),
4776+
i.srcmd5,
4777+
i.comment,
4778+
i.requestid,
47784779
)
47794780
)
47804781
f.seek(0)
@@ -4783,42 +4784,42 @@ def get_commitlog(
47834784

47844785
if format == "xml":
47854786
root = ET.Element("log")
4786-
for revision in reversed(revision_list):
4787+
for i in reversed(revision_list):
47874788
entry = ET.SubElement(root, "logentry")
4788-
entry.attrib["revision"] = str(revision.rev)
4789-
entry.attrib["srcmd5"] = revision.srcmd5
4790-
ET.SubElement(entry, "author").text = revision.user
4791-
ET.SubElement(entry, "date").text = revision.get_time_str()
4792-
ET.SubElement(entry, "requestid").text = str(revision.requestid) if revision.requestid else ""
4793-
ET.SubElement(entry, "msg").text = revision.comment or ""
4789+
entry.attrib["revision"] = str(i.rev)
4790+
entry.attrib["srcmd5"] = i.srcmd5
4791+
ET.SubElement(entry, "author").text = i.user
4792+
ET.SubElement(entry, "date").text = i.get_time_str()
4793+
ET.SubElement(entry, "requestid").text = str(i.requestid) if i.requestid else ""
4794+
ET.SubElement(entry, "msg").text = i.comment or ""
47944795
xmlindent(root)
47954796
yield from ET.tostring(root, encoding="utf-8").decode("utf-8").splitlines()
47964797
return
47974798

47984799
if format == "text":
4799-
for revision in reversed(revision_list):
4800+
for i in reversed(revision_list):
48004801
entry = (
4801-
f"r{revision.rev}",
4802-
revision.user,
4803-
revision.get_time_str(),
4804-
revision.srcmd5,
4805-
revision.version,
4806-
f"rq{revision.requestid}" if revision.requestid else ""
4802+
f"r{i.rev}",
4803+
i.user,
4804+
i.get_time_str(),
4805+
i.srcmd5,
4806+
i.version,
4807+
f"rq{i.requestid}" if i.requestid else ""
48074808
)
48084809
yield 76 * "-"
48094810
yield " | ".join(entry)
48104811
yield ""
4811-
yield revision.comment or "<no message>"
4812+
yield i.comment or "<no message>"
48124813
yield ""
48134814
if patch:
48144815
rdiff = server_diff_noex(
48154816
apiurl,
48164817
prj,
48174818
package,
4818-
revision.rev - 1,
4819+
str(i.rev - 1),
48194820
prj,
48204821
package,
4821-
revision.rev,
4822+
str(i.rev),
48224823
meta=meta,
48234824
)
48244825
yield highlight_diff(rdiff).decode("utf-8", errors="replace")
@@ -5158,7 +5159,7 @@ def owner(
51585159
return res
51595160

51605161

5161-
def set_link_rev(apiurl: str, project: str, package: str, revision="", expand=False, msg: str=None, vrev: str=None):
5162+
def set_link_rev(apiurl: str, project: str, package: str, revision="", expand=False, msg: Optional[str] = None, vrev: Optional[str] = None):
51625163
url = makeurl(apiurl, ["source", project, package, "_link"])
51635164
try:
51645165
f = http_GET(url)
@@ -5179,7 +5180,7 @@ def set_link_rev(apiurl: str, project: str, package: str, revision="", expand=Fa
51795180
return revision
51805181

51815182

5182-
def _set_link_rev(apiurl: str, project: str, package: str, root, revision="", expand=False, setvrev: str=None):
5183+
def _set_link_rev(apiurl: str, project: str, package: str, root, revision="", expand=False, setvrev: Optional[str] = None):
51835184
"""
51845185
Updates the rev attribute of the _link xml. If revision is set to None
51855186
the rev and vrev attributes are removed from the _link xml.

osc/meter.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ def create_text_meter(*args, **kwargs) -> TextMeterBase:
102102

103103
use_pb_fallback = kwargs.pop("use_pb_fallback", False)
104104

105-
meter_class: TextMeterBase
106105
if config.quiet:
107106
meter_class = NoTextMeter
108107
elif not have_pb_module or not config.show_download_progress or not sys.stdout.isatty() or use_pb_fallback:

0 commit comments

Comments
 (0)