Skip to content

Commit

Permalink
Add typechecking (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
ClaudiuGeorgiu authored Jul 28, 2024
1 parent d32a140 commit 77518c8
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 91 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
fail-fast: false
matrix:
python-version: [ 3.8, 3.9, '3.10', '3.11', '3.12' ]
os: [ macOS-latest ]
os: [ macOS-13 ]

steps:
- name: Checkout repository
Expand All @@ -37,12 +37,12 @@ jobs:
run: |
export PATH="${PATH}:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools"
sudo chmod a+x ${ANDROID_HOME}/cmdline-tools/latest/bin/avdmanager
echo yes | sudo -E env "PATH=$PATH" sdkmanager "emulator" "system-images;android-25;default;x86" | grep -v = || true
echo yes | sudo -E env "PATH=$PATH" sdkmanager "emulator" "platform-tools" "system-images;android-25;default;x86" | grep -v = || true
echo no | avdmanager create avd -f -n test -k "system-images;android-25;default;x86" --abi x86
${ANDROID_HOME}/emulator/emulator -avd test -no-window -no-audio -no-boot-anim -no-snapshot -no-accel -gpu guest &
${ANDROID_HOME}/emulator/emulator -avd test -no-window -no-audio -no-boot-anim -no-snapshot -no-metrics -gpu swiftshader_indirect -accel on &
adb wait-for-device shell 'until getprop init.svc.bootanim 2>&1 | grep -q "stopped"; do echo "--- checking emulator ---"; sleep 5; done;'
adb wait-for-device shell 'until pm get-install-location; do echo "--- checking emulator ---"; sleep 5; done;'
adb wait-for-device shell 'sleep 120'
adb wait-for-device shell 'sleep 10'
- name: Run tests
run: |
Expand All @@ -60,4 +60,5 @@ jobs:
- name: Upload tests coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
29 changes: 29 additions & 0 deletions .github/workflows/typecheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Typecheck

on:
push:
branches:
- master
pull_request:

jobs:
typecheck:
name: Typecheck code with mypy
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: pip
cache-dependency-path: requirements*.txt

- name: Install Python packages
run: |
python -m pip install --upgrade pip mypy
python -m pip install -r ./requirements.txt
- name: Typecheck code with mypy
run: mypy adb test
13 changes: 10 additions & 3 deletions .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4

- name: Enable KVM group perms
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
Expand All @@ -36,12 +42,12 @@ jobs:
run: |
export PATH="${PATH}:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools"
sudo chmod a+x ${ANDROID_HOME}/cmdline-tools/latest/bin/avdmanager
echo yes | sudo -E env "PATH=$PATH" sdkmanager "emulator" "system-images;android-25;default;x86" | grep -v = || true
echo yes | sudo -E env "PATH=$PATH" sdkmanager "emulator" "platform-tools" "system-images;android-25;default;x86" | grep -v = || true
echo no | avdmanager create avd -f -n test -k "system-images;android-25;default;x86" --abi x86
${ANDROID_HOME}/emulator/emulator -avd test -no-window -no-audio -no-boot-anim -no-snapshot -no-accel -gpu guest &
${ANDROID_HOME}/emulator/emulator -avd test -no-window -no-audio -no-boot-anim -no-snapshot -no-metrics -accel on &
adb wait-for-device shell 'until getprop init.svc.bootanim 2>&1 | grep -q "stopped"; do echo "--- checking emulator ---"; sleep 5; done;'
adb wait-for-device shell 'until pm get-install-location; do echo "--- checking emulator ---"; sleep 5; done;'
adb wait-for-device shell 'sleep 120'
adb wait-for-device shell 'sleep 10'
- name: Run tests
run: |
Expand All @@ -59,4 +65,5 @@ jobs:
- name: Upload tests coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
62 changes: 0 additions & 62 deletions .github/workflows/windows.yml

This file was deleted.

1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
[![Codacy](https://app.codacy.com/project/badge/Grade/18fa128fe8414a79a32c126f036dd6ac)](https://app.codacy.com/gh/ClaudiuGeorgiu/PythonADB)
[![Ubuntu Build Status](https://github.com/ClaudiuGeorgiu/PythonADB/actions/workflows/ubuntu.yml/badge.svg)](https://github.com/ClaudiuGeorgiu/PythonADB/actions/workflows/ubuntu.yml)
[![Windows Build Status](https://github.com/ClaudiuGeorgiu/PythonADB/actions/workflows/windows.yml/badge.svg)](https://github.com/ClaudiuGeorgiu/PythonADB/actions/workflows/windows.yml)
[![MacOS Build Status](https://github.com/ClaudiuGeorgiu/PythonADB/actions/workflows/macos.yml/badge.svg)](https://github.com/ClaudiuGeorgiu/PythonADB/actions/workflows/macos.yml)
[![Code Coverage](https://codecov.io/gh/ClaudiuGeorgiu/PythonADB/badge.svg)](https://codecov.io/gh/ClaudiuGeorgiu/PythonADB)
[![Python Version](https://img.shields.io/badge/Python-3.8%2B-green.svg?logo=python&logoColor=white)](https://www.python.org/downloads/)
Expand Down
33 changes: 16 additions & 17 deletions adb/adb.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@


class ADB:
def __init__(self, device: str = None, debug: bool = False):
def __init__(self, device: Optional[str] = None, debug: bool = False):
"""
Android Debug Bridge (adb) object constructor.
Expand All @@ -32,14 +32,11 @@ def __init__(self, device: str = None, debug: bool = False):

# If adb executable is not added to PATH variable, it can be specified by
# using the ADB_PATH environment variable.
if "ADB_PATH" in os.environ:
self.adb_path: str = os.environ["ADB_PATH"]
else:
self.adb_path: str = "adb"
self.adb_path: str = os.environ.get("ADB_PATH", "adb")

# Make sure to use the full path of the executable (needed for cross-platform
# compatibility).
self.adb_path = shutil.which(self.adb_path)
self.adb_path = shutil.which(self.adb_path) # type: ignore

if not self.is_available():
raise FileNotFoundError(
Expand All @@ -49,7 +46,7 @@ def __init__(self, device: str = None, debug: bool = False):
)

@property
def target_device(self) -> str:
def target_device(self) -> Optional[str]:
return self._device

@target_device.setter
Expand Down Expand Up @@ -169,7 +166,7 @@ def get_version(self, timeout: Optional[int] = None) -> str:
:return: A string containing the version of the installed adb.
"""

output = self.execute(["version"], timeout=timeout)
output: str = self.execute(["version"], timeout=timeout) # type: ignore[assignment]

match = re.search(r"version\s(\S+)", output)
if match:
Expand All @@ -186,7 +183,7 @@ def get_available_devices(self, timeout: Optional[int] = None) -> List[str]:
:return: A list of strings, each string is a device serial number.
"""

output = self.execute(["devices"], timeout=timeout)
output: str = self.execute(["devices"], timeout=timeout) # type: ignore[assignment]

devices = []
for line in output.splitlines():
Expand Down Expand Up @@ -236,7 +233,8 @@ def get_property(self, property_name: str, timeout: Optional[int] = None) -> str
:return: The value of the property.
"""

return self.shell(["getprop", property_name], timeout=timeout)
property: str = self.shell(["getprop", property_name], timeout=timeout) # type: ignore[assignment]
return property

def get_device_sdk_version(self, timeout: Optional[int] = None) -> int:
"""
Expand Down Expand Up @@ -271,7 +269,7 @@ def kill_server(self, timeout: Optional[int] = None) -> None:

self.execute(["kill-server"], timeout=timeout)

def connect(self, host: str = None, timeout: Optional[int] = None) -> str:
def connect(self, host: Optional[str] = None, timeout: Optional[int] = None) -> str:
"""
Start an adb server and (optionally) connect to an Android device.
Expand All @@ -289,7 +287,7 @@ def connect(self, host: str = None, timeout: Optional[int] = None) -> str:
else:
connect_cmd = ["start-server"]

output = self.execute(connect_cmd, timeout=timeout)
output: str = self.execute(connect_cmd, timeout=timeout) # type: ignore[assignment]

# Make sure the connect operation ended successfully.
if output and any(
Expand Down Expand Up @@ -335,7 +333,8 @@ def reboot(self, timeout: Optional[int] = None) -> str:
before throwing an exception.
"""

return self.execute(["reboot"], timeout=timeout)
output: str = self.execute(["reboot"], timeout=timeout) # type: ignore[assignment]
return output

def push_file(
self,
Expand Down Expand Up @@ -380,7 +379,7 @@ def push_file(

push_cmd.append(device_path)

output = self.execute(push_cmd, timeout=timeout)
output: str = self.execute(push_cmd, timeout=timeout) # type: ignore[assignment]

# Make sure the push operation ended successfully.
match = re.search(r"\d+ files? pushed[.,]", output.splitlines()[-1])
Expand Down Expand Up @@ -438,7 +437,7 @@ def pull_file(

pull_cmd.append(host_path)

output = self.execute(pull_cmd, timeout=timeout)
output: str = self.execute(pull_cmd, timeout=timeout) # type: ignore[assignment]

# Make sure the pull operation ended successfully.
match = re.search(r"\d+ files? pulled[.,]", output.splitlines()[-1])
Expand Down Expand Up @@ -484,7 +483,7 @@ def install_app(

install_cmd.append(apk_path)

output = self.execute(install_cmd, timeout=timeout)
output: str = self.execute(install_cmd, timeout=timeout) # type: ignore[assignment]

# Make sure the installation operation ended successfully.
# Complete list of error messages:
Expand All @@ -509,7 +508,7 @@ def uninstall_app(self, package_name: str, timeout: Optional[int] = None):

uninstall_cmd = ["uninstall", package_name]

output = self.execute(uninstall_cmd, timeout=timeout)
output: str = self.execute(uninstall_cmd, timeout=timeout) # type: ignore[assignment]

# Make sure the uninstallation operation ended successfully.
# Complete list of error messages:
Expand Down
6 changes: 2 additions & 4 deletions test/test_adb.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,11 @@ def test_adb_execute_async_command(self, adb_instance: ADB):

def test_adb_execute_invalid_command(self, adb_instance: ADB):
with pytest.raises(TypeError):
# noinspection PyTypeChecker
adb_instance.execute("not a list of strings")
adb_instance.execute("not a list of strings") # type: ignore

def test_adb_shell_invalid_command(self, adb_instance: ADB):
with pytest.raises(TypeError):
# noinspection PyTypeChecker
adb_instance.shell("not a list of strings")
adb_instance.shell("not a list of strings") # type: ignore

def test_adb_execute_invalid_timeout(self, adb_instance: ADB):
with pytest.raises(ValueError):
Expand Down

0 comments on commit 77518c8

Please sign in to comment.