Skip to content

Commit e02ea42

Browse files
committed
Update to work with python 3.13 and begin moving away from os.path
1 parent 0684e3a commit e02ea42

8 files changed

Lines changed: 44 additions & 36 deletions

File tree

docker-compose.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ services:
1010
environment:
1111
- PYTHONPATH=/code
1212
- PYTHONUNBUFFERED=0
13-
command: sh -c "pip install -r requirements.txt;py.test test -s -v --junit-xml test_result.xml;pip install 'aiofiles>=0.4.0';py.test test_async -s -v --junit-xml test_result_async.xml"
13+
command: sh -c "pip install -r requirements.txt;pip install 'Exscript';py.test test -s -v --junit-xml test_result.xml;pip install 'aiofiles>=0.4.0';py.test test_async -s -v --junit-xml test_result_async.xml; sleep 1800"
1414

1515
emulator:
1616
image: swind/android-emulator:android_28
@@ -19,5 +19,7 @@ services:
1919
- ANDROID_EMULATOR_EXTRA_ARGS=-skin 1080x1920 -memory 2048 -no-boot-anim -gpu host -qemu
2020
ports:
2121
- 6080:6080
22+
group_add:
23+
- keep-groups
2224
devices:
2325
- "/dev/kvm:/dev/kvm"

ppadb/device.py

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import re
22
import os
3+
from pathlib import Path, PurePosixPath
34

45
from ppadb.command.transport import Transport
56
from ppadb.command.serial import Serial
@@ -30,17 +31,6 @@
3031
from pipes import quote as cmd_quote
3132

3233

33-
def _get_src_info(src):
34-
"""Get information about the contents of a folder; used in :meth:`Device.push`."""
35-
exists = os.path.exists(src)
36-
isfile = os.path.isfile(src)
37-
isdir = os.path.isdir(src)
38-
basename = os.path.basename(src)
39-
walk = None if not isdir else list(os.walk(src))
40-
41-
return exists, isfile, isdir, basename, walk
42-
43-
4434
class Device(Transport, Serial, Input, Utils, WM, Traffic, CPUStat, BatteryStats):
4535
INSTALL_RESULT_PATTERN = "(Success|Failure|Error)\s?(.*)"
4636
UNINSTALL_RESULT_PATTERN = "(Success|Failure.*|.*Unknown package:.*)"
@@ -66,22 +56,23 @@ def _push(self, src, dest, mode, progress):
6656
sync.push(src, dest, mode, progress)
6757

6858
def push(self, src, dest, mode=0o644, progress=None):
69-
exists, isfile, isdir, basename, walk = _get_src_info(src)
70-
if not exists:
59+
src = Path(src)
60+
dest = PurePosixPath(dest)
61+
if not src.exists():
7162
raise FileNotFoundError("Cannot find {}".format(src))
7263

73-
if isfile:
64+
if src.is_file():
7465
self._push(src, dest, mode, progress)
66+
elif src.is_dir():
67+
src.resolve()
68+
for root, dirs, files in src.walk():
69+
subdir = root.relative_to(src)
70+
destdir = dest / src.name / subdir
7571

76-
elif isdir:
77-
for root, dirs, files in walk:
78-
subdir = os.path.relpath(root, src)
79-
root_dir_path = os.path.normpath(os.path.join(basename, subdir))
80-
81-
self.shell('mkdir -p "{}"'.format(os.path.normpath(os.path.join(dest, root_dir_path))))
72+
self.shell(f'mkdir -p "{destdir}"')
8273

8374
for item in files:
84-
self._push(os.path.normpath(os.path.join(root, item)), os.path.normpath(os.path.join(dest, root_dir_path, item)), mode, progress)
75+
self._push(root / item, destdir / item, mode, progress)
8576

8677
def pull(self, src, dest):
8778
sync_conn = self.sync()

ppadb/device_async.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
except ImportError: # pragma: no cover
44
from asyncio import get_event_loop as get_running_loop # Python 3.6 compatibility
55

6-
import re
76
import os
7+
from pathlib import Path, PurePosixPath
8+
import re
89

910
from ppadb.command.transport_async import TransportAsync
10-
from ppadb.device import _get_src_info
1111
from ppadb.sync_async import SyncAsync
1212

1313

@@ -36,22 +36,23 @@ async def _push(self, src, dest, mode, progress):
3636
await sync.push(src, dest, mode, progress)
3737

3838
async def push(self, src, dest, mode=0o644, progress=None):
39-
exists, isfile, isdir, basename, walk = await get_running_loop().run_in_executor(None, _get_src_info, src)
40-
if not exists:
39+
src = Path(src)
40+
dest = PurePosixPath(dest)
41+
if not src.exists():
4142
raise FileNotFoundError("Cannot find {}".format(src))
4243

43-
if isfile:
44+
if src.is_file():
4445
await self._push(src, dest, mode, progress)
46+
elif src.is_dir():
47+
src.resolve()
48+
for root, dirs, files in src.walk():
49+
subdir = root.relative_to(src)
50+
destdir = dest / src.name / subdir
4551

46-
elif isdir:
47-
for root, dirs, files in walk:
48-
subdir = os.path.relpath(root, src)
49-
root_dir_path = os.path.normpath(os.path.join(basename, subdir))
50-
51-
await self.shell('mkdir -p "{}"'.format(os.path.normpath(os.path.join(dest, root_dir_path))))
52+
await self.shell(f'mkdir -p "{destdir}"')
5253

5354
for item in files:
54-
await self._push(os.path.normpath(os.path.join(root, item)), os.path.normpath(os.path.join(dest, root_dir_path, item)), mode, progress)
55+
await self._push(root / item, destdir / item, mode, progress)
5556

5657
async def pull(self, src, dest):
5758
sync_conn = await self.sync()

test/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import time
2-
import telnetlib
2+
import Exscript.protocols.telnetlib as telnetlib
33

44
import pytest
55

test/test_device.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,16 @@ def test_push_dir(device):
148148
assert "app-x86.apk" in result
149149

150150

151+
def test_push_recurse_dir(device):
152+
dir_path = os.path.dirname(os.path.realpath(__file__))
153+
apk_path = os.path.join(dir_path, "resources")
154+
device.push(apk_path, "/sdcard")
155+
156+
result = device.shell("ls /sdcard/resources/apk")
157+
assert "app-armeabi-v7a.apk" in result
158+
assert "app-x86.apk" in result
159+
160+
151161
def test_push_with_progress(device):
152162
dir_path = os.path.dirname(os.path.realpath(__file__))
153163
apk_path = os.path.join(dir_path, "resources/apk/app-x86.apk")

test_async/async_wrapper.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
def _await(coro):
77
with warnings.catch_warnings(record=True) as warns:
8+
loop = asyncio.new_event_loop()
9+
asyncio.set_event_loop(loop)
810
ret = asyncio.get_event_loop().run_until_complete(coro)
911

1012
if warns:

test_async/test_client_async.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ async def test_create_connection_fail(self):
2424
with self.assertRaises(RuntimeError):
2525
await self.client.create_connection()
2626

27+
2728
@awaiter
2829
async def test_device_returns_none(self):
2930
with async_patch('asyncio.open_connection', return_value=(FakeStreamReader(), FakeStreamWriter())):

test_async/test_device_async.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import asyncio
77
from contextlib import asynccontextmanager
88
import os
9+
import pathlib
910
import sys
1011
import unittest
1112
from unittest.mock import mock_open, patch
@@ -82,7 +83,7 @@ def progress(*args, **kwargs):
8283

8384
@awaiter
8485
async def test_push_dir(self):
85-
with patch('os.path.exists', return_value=True), patch('os.path.isfile', return_value=False), patch('os.path.isdir', return_value=True), patch('os.walk', return_value=[('root1', 'dirs1', 'files1'), ('root2', 'dirs2', 'files2')]):
86+
with patch('pathlib.Path.exists', return_value=True), patch('os.path.isfile', return_value=False), patch('os.path.isdir', return_value=True), patch('os.walk', return_value=[('root1', 'dirs1', 'files1'), ('root2', 'dirs2', 'files2')]):
8687
with async_patch('ppadb.device_async.DeviceAsync.shell'), async_patch('ppadb.device_async.DeviceAsync._push'):
8788
await self.device.push('src', 'dest')
8889

0 commit comments

Comments
 (0)