Skip to content

Commit

Permalink
Enable typeguard during build time and tests, fix issues found
Browse files Browse the repository at this point in the history
  • Loading branch information
dmach committed May 13, 2024
1 parent 98a9b83 commit c1fb29c
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 33 deletions.
1 change: 1 addition & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ jobs:
sudo sh -c '. /etc/os-release; echo "deb [trusted=yes] http://download.opensuse.org/repositories/openSUSE:Tools/xUbuntu_${VERSION_ID} ./" > /etc/apt/sources.list.d/openSUSE-Tools.list'
sudo apt-get -y update
sudo apt-get -y --no-install-recommends install python3-behave diffstat diffutils python3 python3-cryptography python3-pip python3-rpm python3-setuptools python3-urllib3 obs-build obs-service-set-version
sudo pip3 install typeguard
- name: "Checkout sources"
uses: actions/checkout@v3
Expand Down
10 changes: 10 additions & 0 deletions contrib/osc.spec
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
%bcond_with fdupes
%endif

# use typeguard during build on distros where typeguard is available
%if (0%{?suse_version} > 1500 || 0%{?fedora} >= 37)
%bcond_without typeguard
%else
%bcond_with typeguard
%endif

%define argparse_manpage_pkg argparse-manpage
%define obs_build_pkg obs-build
%define ssh_add_pkg openssh-clients
Expand Down Expand Up @@ -69,6 +76,9 @@ BuildRequires: %{use_python_pkg}-cryptography
BuildRequires: %{use_python_pkg}-devel >= 3.6
BuildRequires: %{use_python_pkg}-rpm
BuildRequires: %{use_python_pkg}-setuptools
%if %{with typeguard}
BuildRequires: %{use_python_pkg}-typeguard
%endif
BuildRequires: %{use_python_pkg}-urllib3
BuildRequires: diffstat
%if %{with fdupes}
Expand Down
23 changes: 23 additions & 0 deletions osc-wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,29 @@
This wrapper allows osc to be called from the source directory during development.
"""


import os


USE_TYPEGUARD = os.environ.get("OSC_TYPEGUARD", "1").lower() in ("1", "true", "on")

if USE_TYPEGUARD:
try:
from typeguard import install_import_hook
except ImportError:
install_import_hook = None

if install_import_hook is None:
try:
from typeguard.importhook import install_import_hook
except ImportError:
install_import_hook = None

if install_import_hook:
# install typeguard import hook only if available
install_import_hook("osc")


import osc.babysitter

osc.babysitter.main()
28 changes: 14 additions & 14 deletions osc/commandline.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,10 +594,10 @@ def pop_args(
args,
arg1_name: str = None,
arg1_is_optional: bool = False,
arg1_default: str = None,
arg1_default: Optional[str] = None,
arg2_name: str = None,
arg2_is_optional: bool = False,
arg2_default: str = None,
arg2_default: Optional[str] = None,
):
"""
Pop 2 arguments from `args`.
Expand Down Expand Up @@ -669,9 +669,9 @@ def pop_args(
def pop_project_package_from_args(
args: List[str],
project_is_optional: bool = False,
default_project: str = None,
default_project: Optional[str] = None,
package_is_optional: bool = False,
default_package: str = None,
default_package: Optional[str] = None,
):
"""
Pop project and package from given `args`.
Expand Down Expand Up @@ -740,9 +740,9 @@ def pop_project_package_from_args(
def pop_repository_arch_from_args(
args: List[str],
repository_is_optional: bool = False,
default_repository: str = None,
default_repository: Optional[str] = None,
arch_is_optional: bool = False,
default_arch: str = None,
default_arch: Optional[str] = None,
):
"""
Pop repository and arch from given `args`.
Expand Down Expand Up @@ -779,13 +779,13 @@ def pop_repository_arch_from_args(
def pop_project_package_repository_arch_from_args(
args: List[str],
project_is_optional: bool = False,
default_project: str = None,
default_project: Optional[str] = None,
package_is_optional: bool = False,
default_package: str = None,
default_package: Optional[str] = None,
repository_is_optional: bool = False,
default_repository: str = None,
default_repository: Optional[str] = None,
arch_is_optional: bool = False,
default_arch: str = None,
default_arch: Optional[str] = None,
):
"""
Pop project, package, repository and arch from given `args`.
Expand Down Expand Up @@ -865,13 +865,13 @@ def pop_project_package_repository_arch_from_args(
def pop_project_package_targetproject_targetpackage_from_args(
args: List[str],
project_is_optional: bool = False,
default_project: str = None,
default_project: Optional[str] = None,
package_is_optional: bool = False,
default_package: str = None,
default_package: Optional[str] = None,
target_project_is_optional: bool = False,
default_target_project: str = None,
default_target_project: Optional[str] = None,
target_package_is_optional: bool = False,
default_target_package: str = None,
default_target_package: Optional[str] = None,
):
"""
Pop project, package, target project and target package from given `args`.
Expand Down
30 changes: 15 additions & 15 deletions osc/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2319,7 +2319,7 @@ def get_request_collection(
package=None,
states=None,
review_states=None,
types: List[str] = None,
types: Optional[List[str]] = None,
ids=None,
withfullhistory=False
):
Expand Down Expand Up @@ -2862,20 +2862,20 @@ def get_source_file_diff(dir, filename, rev, oldfilename=None, olddir=None, orig

def server_diff(
apiurl: str,
old_project: str,
old_package: str,
old_revision: str,
old_project: Optional[str],
old_package: Optional[str],
old_revision: Optional[str],
new_project: str,
new_package: str,
new_revision: str,
new_revision: Optional[str],
unified=False,
missingok=False,
meta=False,
expand=True,
onlyissues=False,
full=True,
xml=False,
files: list = None,
files: Optional[list] = None,
):
query: Dict[str, Union[str, int]] = {"cmd": "diff"}
if expand:
Expand Down Expand Up @@ -2928,19 +2928,19 @@ def server_diff(

def server_diff_noex(
apiurl: str,
old_project: str,
old_package: str,
old_revision: str,
old_project: Optional[str],
old_package: Optional[str],
old_revision: Optional[str],
new_project: str,
new_package: str,
new_revision: str,
new_revision: Optional[str],
unified=False,
missingok=False,
meta=False,
expand=True,
onlyissues=False,
xml=False,
files: list = None,
files: Optional[list] = None,
):
try:
return server_diff(apiurl,
Expand Down Expand Up @@ -3087,7 +3087,7 @@ def checkout_package(
pathname=None,
prj_obj=None,
expand_link=False,
prj_dir: Path=None,
prj_dir: Optional[Path] = None,
server_service_files=None,
service_files=None,
progress_obj=None,
Expand Down Expand Up @@ -3792,7 +3792,7 @@ def copy_pac(
return 'Done.'


def lock(apiurl: str, project: str, package: str, msg: str = None):
def lock(apiurl: str, project: str, package: str, msg: Optional[str] = None):
url_path = ["source", project]
if package:
url_path += [package]
Expand Down Expand Up @@ -5097,7 +5097,7 @@ def owner(
return res


def set_link_rev(apiurl: str, project: str, package: str, revision="", expand=False, msg: str=None, vrev: str=None):
def set_link_rev(apiurl: str, project: str, package: str, revision="", expand=False, msg: Optional[str] = None, vrev: Optional[str] = None):
url = makeurl(apiurl, ["source", project, package, "_link"])
try:
f = http_GET(url)
Expand All @@ -5118,7 +5118,7 @@ def set_link_rev(apiurl: str, project: str, package: str, revision="", expand=Fa
return revision


def _set_link_rev(apiurl: str, project: str, package: str, root, revision="", expand=False, setvrev: str=None):
def _set_link_rev(apiurl: str, project: str, package: str, root, revision="", expand=False, setvrev: Optional[str] = None):
"""
Updates the rev attribute of the _link xml. If revision is set to None
the rev and vrev attributes are removed from the _link xml.
Expand Down
2 changes: 1 addition & 1 deletion osc/meter.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def end(self):
self.bar.finish()


class NoPBTextMeter:
class NoPBTextMeter(TextMeterBase):
def start(self, basename: str, size: Optional[int] = None):
pass

Expand Down
6 changes: 4 additions & 2 deletions osc/output/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import subprocess
import sys
import tempfile
from typing import BinaryIO
from typing import Dict
from typing import Generator
from typing import List
from typing import Optional
from typing import TextIO
Expand Down Expand Up @@ -137,7 +139,7 @@ def safe_print(*args, **kwargs):
print(*args, **kwargs)


def safe_write(file: TextIO, text: Union[str, bytes], *, add_newline: bool = False):
def safe_write(file: Union[BinaryIO, TextIO], text: Union[str, bytes], *, add_newline: bool = False):
"""
Run sanitize_text() on ``text`` and write it to ``file``.
Expand Down Expand Up @@ -211,7 +213,7 @@ def run_pager(message: Union[bytes, str], tmp_suffix: str = ""):
run_external(*cmd, env=env)


def pipe_to_pager(lines: Union[List[bytes], List[str]], *, add_newlines=False):
def pipe_to_pager(lines: Union[List[bytes], List[str], Generator[bytes, None, None], Generator[str, None, None]], *, add_newlines=False):
"""
Pipe ``lines`` to the pager.
If running in a non-interactive terminal, print the data instead.
Expand Down
19 changes: 18 additions & 1 deletion osc/util/safewriter.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,39 @@
import io

# be careful when debugging this code:
# don't add print statements when setting sys.stdout = SafeWriter(sys.stdout)...
class SafeWriter:
class SafeWriter(io.TextIOBase):
"""
Safely write an (unicode) str. In case of an "UnicodeEncodeError" the
the str is encoded with the "encoding" encoding.
All getattr, setattr calls are passed through to the "writer" instance.
"""

def __init__(self, writer, encoding='unicode_escape'):
super().__init__()
self._writer = writer
self._encoding = encoding

# TextIOBase requires overriding the following stub methods: detach, read, readline, and write

def detach(self, *args, **kwargs):
return self._writer.detach(*args, **kwargs)

def read(self, *args, **kwargs):
return self._writer.read(args, **kwargs)

def readline(self, *args, **kwargs):
return self._writer.readline(args, **kwargs)

def write(self, s):
try:
self._writer.write(s)
except UnicodeEncodeError as e:
self._writer.write(s.encode(self._encoding))

def fileno(self, *args, **kwargs):
return self._writer.fileno(*args, **kwargs)

def __getattr__(self, name):
return getattr(self._writer, name)

Expand Down
14 changes: 14 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
try:
from typeguard import install_import_hook
except ImportError:
install_import_hook = None

if not install_import_hook:
try:
from typeguard.importhook import install_import_hook
except ImportError:
install_import_hook = None

if install_import_hook:
# install typeguard import hook only if available
install_import_hook("osc")

0 comments on commit c1fb29c

Please sign in to comment.