The package name has been renamed from 'adb' to 'ppadb'
=========================================================
From version **v0.2.1-dev**, the package name has been renamed from 'adb' to 'ppadb' to avoid conflit with Google `google/python-adb`_
Introduction
==================
This is pure-python implementation of the ADB client.
You can use it to communicate with adb server (not the adb daemon on the device/emulator).
When you use `adb` command
.. image:: https://raw.githubusercontent.com/Swind/pure-python-adb/master/docs/adb_cli.png
Now you can use `pure-python-adb` to connect to adb server as adb command line
.. image:: https://raw.githubusercontent.com/Swind/pure-python-adb/master/docs/adb_pure_python_adb.png
This package supports most of the adb command line tool's functionality.
1. adb devices
2. adb shell
3. adb forward
4. adb pull/push
5. adb install/uninstall
Requirements
============
Python 3.6+
Installation
============
.. code-block:: console
$pip install -U pure-python-adb
Examples
========
Connect to adb server and get the version
-----------------------------------------
.. code-block:: python
from ppadb.client import Client as AdbClient
# Default is "127.0.0.1" and 5037
client = AdbClient(host="127.0.0.1", port=5037)
print(client.version())
>>> 39
Connect to a device
-------------------
.. code-block:: python
from ppadb.client import Client as AdbClient
# Default is "127.0.0.1" and 5037
client = AdbClient(host="127.0.0.1", port=5037)
device = client.device("emulator-5554")
List all devices ( adb devices ) and install/uninstall an APK on all devices
----------------------------------------------------------------------------------
.. code-block:: python
from ppadb.client import Client as AdbClient
apk_path = "example.apk"
# Default is "127.0.0.1" and 5037
client = AdbClient(host="127.0.0.1", port=5037)
devices = client.devices()
for device in devices:
device.install(apk_path)
# Check apk is installed
for device in devices:
print(device.is_installed("example.package"))
# Uninstall
for device in devices:
device.uninstall("example.package")
adb shell
---------
.. code-block:: python
from ppadb.client import Client as AdbClient
# Default is "127.0.0.1" and 5037
client = AdbClient(host="127.0.0.1", port=5037)
device = client.device("emulator-5554")
device.shell("echo hello world !")
.. code-block:: python
def dump_logcat(connection):
while True:
data = connection.read(1024)
if not data:
break
print(data.decode('utf-8'))
connection.close()
from ppadb.client import Client as AdbClient
# Default is "127.0.0.1" and 5037
client = AdbClient(host="127.0.0.1", port=5037)
device = client.device("emulator-5554")
device.shell("logcat", handler=dump_logcat)
read logcat line by line
.. code-block:: python
from ppadb.client import Client
def dump_logcat_by_line(connect):
file_obj = connect.socket.makefile()
for index in range(0, 10):
print("Line {}: {}".format(index, file_obj.readline().strip()))
file_obj.close()
connect.close()
client = Client()
device = client.device("emulator-5554")
device.shell("logcat", handler=dump_logcat_by_line)
Screenshot
----------
.. code-block:: python
from ppadb.client import Client as AdbClient
client = AdbClient(host="127.0.0.1", port=5037)
device = client.device("emulator-5554")
result = device.screencap()
with open("screen.png", "wb") as fp:
fp.write(result)
Push file or folder
--------------------
.. code-block:: python
from ppadb.client import Client as AdbClient
client = AdbClient(host="127.0.0.1", port=5037)
device = client.device("emulator-5554")
device.push("example.apk", "/sdcard/example.apk")
Pull
----
.. code-block:: python
from ppadb.client import Client as AdbClient
client = AdbClient(host="127.0.0.1", port=5037)
device = client.device("emulator-5554")
device.shell("screencap -p /sdcard/screen.png")
device.pull("/sdcard/screen.png", "screen.png")
Connect to device
-----------------
.. code-block:: python
from ppadb.client import Client as AdbClient
client = AdbClient(host="127.0.0.1", port=5037)
client.remote_connect("172.20.0.1", 5555)
device = client.device("172.20.0.1:5555")
# Disconnect all devices
client.remote_disconnect()
##Disconnect 172.20.0.1
# client.remote_disconnect("172.20.0.1")
##Or
# client.remote_disconnect("172.20.0.1", 5555)
Enable debug logger
--------------------
.. code-block:: python
logging.getLogger("ppadb").setLevel(logging.DEBUG)
Async Client
--------------------
.. code-block:: python
import asyncio
import aiofiles
from ppadb.client_async import ClientAsync as AdbClient
async def _save_screenshot(device):
result = await device.screencap()
file_name = f"{device.serial}.png"
async with aiofiles.open(f"{file_name}", mode='wb') as f:
await f.write(result)
return file_name
async def main():
client = AdbClient(host="127.0.0.1", port=5037)
devices = await client.devices()
for device in devices:
print(device.serial)
result = await asyncio.gather(*[_save_screenshot(device) for device in devices])
print(result)
asyncio.run(main())
How to run test cases
======================
Prepare
--------
1. Install Docker
2. Install Docker Compose
.. code-block:: console
pip install docker-compose
3. Modify `test/conftest.py`
Change the value of `adb_host` to the "emulator"
.. code-block:: python
adb_host="emulator"
4. Run testcases
.. code-block:: console
docker-compose up
Result
.. code-block:: console
Starting purepythonadb_emulator_1 ... done
Recreating purepythonadb_python_environment_1 ... done
Attaching to purepythonadb_emulator_1, purepythonadb_python_environment_1
emulator_1 | + echo n
emulator_1 | + /home/user/android-sdk-linux/tools/bin/avdmanager create avd -k system-images;android-25;google_apis;x86 -n Docker -b x86 -g google_apis --device 8 --force
Parsing /home/user/android-sdk-linux/emulator/package.xmlParsing /home/user/android-sdk-linux/patcher/v4/package.xmlParsing /home/user/android-sdk-linux/platform-tools/package.xmlParsing /home/user/android-sdk-linux/platforms/android-25/package.xmlParsing /home/user/android-sdk-linux/system-images/android-25/google_apis/x86/package.xmlParsing /home/user/android-sdk-linux/tools/package.xml+ echo hw.keyboard = true
emulator_1 | + adb start-server
emulator_1 | * daemon not running; starting now at tcp:5037
python_environment_1 | ============================= test session starts ==============================
python_environment_1 | platform linux -- Python 3.6.1, pytest-3.6.3, py-1.5.4, pluggy-0.6.0
python_environment_1 | rootdir: /code, inifile:
python_environment_1 | collected 27 items
python_environment_1 |
emulator_1 | * daemon started successfully
emulator_1 | + exec /usr/bin/supervisord
emulator_1 | /usr/lib/python2.7/dist-packages/supervisor/options.py:298: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a "-c" argument specifying an absolute path to a configuration file for improved security.
emulator_1 | 'Supervisord is running as root and it is searching '
emulator_1 | 2018-07-07 17:19:47,560 CRIT Supervisor running as root (no user in config file)
emulator_1 | 2018-07-07 17:19:47,560 INFO Included extra file "/etc/supervisor/conf.d/supervisord.conf" during parsing
emulator_1 | 2018-07-07 17:19:47,570 INFO RPC interface 'supervisor' initialized
emulator_1 | 2018-07-07 17:19:47,570 CRIT Server 'unix_http_server' running without any HTTP authentication checking
emulator_1 | 2018-07-07 17:19:47,570 INFO supervisord started with pid 1
emulator_1 | 2018-07-07 17:19:48,573 INFO spawned: 'socat-5554' with pid 74
emulator_1 | 2018-07-07 17:19:48,574 INFO spawned: 'socat-5555' with pid 75
emulator_1 | 2018-07-07 17:19:48,576 INFO spawned: 'socat-5037' with pid 76
emulator_1 | 2018-07-07 17:19:48,578 INFO spawned: 'novnc' with pid 77
emulator_1 | 2018-07-07 17:19:48,579 INFO spawned: 'socat-9008' with pid 78
emulator_1 | 2018-07-07 17:19:48,582 INFO spawned: 'emulator' with pid 80
emulator_1 | 2018-07-07 17:19:49,607 INFO success: socat-5554 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
emulator_1 | 2018-07-07 17:19:49,607 INFO success: socat-5555 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
emulator_1 | 2018-07-07 17:19:49,607 INFO success: socat-5037 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
emulator_1 | 2018-07-07 17:19:49,607 INFO success: novnc entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
emulator_1 | 2018-07-07 17:19:49,608 INFO success: socat-9008 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
emulator_1 | 2018-07-07 17:19:49,608 INFO success: emulator entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
python_environment_1 | test/test_device.py .............. [ 51%]
python_environment_1 | test/test_host.py .. [ 59%]
python_environment_1 | test/test_host_serial.py ........ [ 88%]
python_environment_1 | test/test_plugins.py ... [100%]
python_environment_1 |
python_environment_1 | ------------------ generated xml file: /code/test_result.xml -------------------
python_environment_1 | ========================= 27 passed in 119.15 seconds ==========================
purepythonadb_python_environment_1 exited with code 0
Aborting on container exit...
Stopping purepythonadb_emulator_1 ... done
More Information
=================
A pure Node.js client for the Android Debug Bridge
---------------------------------------------------
adbkit_
ADB documents
--------------
- protocol_
- services_
- sync_
.. _adbkit: https://github.com/openstf/stf
.. _protocol: https://android.googlesource.com/platform/system/core/+/master/adb/protocol.txt
.. _services: https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT
.. _sync: https://android.googlesource.com/platform/system/core/+/master/adb/SYNC.TXT
.. _`google/python-adb`: https://github.com/google/python-adb
0.2.1 (2019-10-14)
--------------------
* Fixes #21: Rename the package name from "adb" to "ppadb"
* Fixes #23: Support push dir to device
* Fixes #25: Don't call logging.basicConfig() in the module
0.1.6 (2019-01-21)
-------------------
* Fix #4 push does not preserve original timestap unlike equiv adb push from command line
* Fix #6 forward_list should also check serial
* Fix #8: adb/command/host/__init__.py can take an exception parsing "devices" data
0.1.0 (2018-06-23)
-------------------
* First release on PyPI.
Raw data
{
"_id": null,
"home_page": "https://github.com/Swind/pure-python-adb",
"name": "pure-python-adb",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "adb",
"author": "Swind Ou",
"author_email": "swind@cloudmosa.com",
"download_url": "https://files.pythonhosted.org/packages/0a/b7/1c4d6b2cbe499b4180177abcf3ae2bb2d8b36acf695ae7d8e9eb99ba00ea/pure-python-adb-0.3.0.dev0.tar.gz",
"platform": "",
"description": "The package name has been renamed from 'adb' to 'ppadb'\n=========================================================\n\nFrom version **v0.2.1-dev**, the package name has been renamed from 'adb' to 'ppadb' to avoid conflit with Google `google/python-adb`_\n\n\nIntroduction\n==================\n\nThis is pure-python implementation of the ADB client.\n\nYou can use it to communicate with adb server (not the adb daemon on the device/emulator).\n\nWhen you use `adb` command\n\n.. image:: https://raw.githubusercontent.com/Swind/pure-python-adb/master/docs/adb_cli.png\n\nNow you can use `pure-python-adb` to connect to adb server as adb command line\n\n.. image:: https://raw.githubusercontent.com/Swind/pure-python-adb/master/docs/adb_pure_python_adb.png\n\nThis package supports most of the adb command line tool's functionality.\n\n1. adb devices\n2. adb shell\n3. adb forward\n4. adb pull/push\n5. adb install/uninstall\n\nRequirements\n============\n\nPython 3.6+\n\nInstallation\n============\n\n.. code-block:: console\n\n $pip install -U pure-python-adb\n\nExamples\n========\n\nConnect to adb server and get the version\n-----------------------------------------\n\n.. code-block:: python\n\n from ppadb.client import Client as AdbClient\n # Default is \"127.0.0.1\" and 5037\n client = AdbClient(host=\"127.0.0.1\", port=5037)\n print(client.version())\n\n >>> 39\n\nConnect to a device\n-------------------\n\n.. code-block:: python\n\n from ppadb.client import Client as AdbClient\n # Default is \"127.0.0.1\" and 5037\n client = AdbClient(host=\"127.0.0.1\", port=5037)\n device = client.device(\"emulator-5554\")\n\n\nList all devices ( adb devices ) and install/uninstall an APK on all devices\n----------------------------------------------------------------------------------\n\n.. code-block:: python\n\n from ppadb.client import Client as AdbClient\n\n apk_path = \"example.apk\"\n\n # Default is \"127.0.0.1\" and 5037\n client = AdbClient(host=\"127.0.0.1\", port=5037)\n devices = client.devices()\n\n for device in devices:\n device.install(apk_path)\n\n # Check apk is installed\n for device in devices:\n print(device.is_installed(\"example.package\"))\n\n # Uninstall\n for device in devices:\n device.uninstall(\"example.package\")\n\nadb shell\n---------\n\n.. code-block:: python\n\n from ppadb.client import Client as AdbClient\n # Default is \"127.0.0.1\" and 5037\n client = AdbClient(host=\"127.0.0.1\", port=5037)\n device = client.device(\"emulator-5554\")\n device.shell(\"echo hello world !\")\n\n.. code-block:: python\n\n def dump_logcat(connection):\n while True:\n data = connection.read(1024)\n if not data:\n break\n print(data.decode('utf-8'))\n\n connection.close()\n\n from ppadb.client import Client as AdbClient\n # Default is \"127.0.0.1\" and 5037\n client = AdbClient(host=\"127.0.0.1\", port=5037)\n device = client.device(\"emulator-5554\")\n device.shell(\"logcat\", handler=dump_logcat)\n\nread logcat line by line\n\n.. code-block:: python\n\n from ppadb.client import Client\n\n def dump_logcat_by_line(connect):\n file_obj = connect.socket.makefile()\n for index in range(0, 10):\n print(\"Line {}: {}\".format(index, file_obj.readline().strip()))\n\n file_obj.close()\n connect.close()\n\n client = Client()\n device = client.device(\"emulator-5554\")\n device.shell(\"logcat\", handler=dump_logcat_by_line)\n\nScreenshot\n----------\n\n.. code-block:: python\n\n from ppadb.client import Client as AdbClient\n client = AdbClient(host=\"127.0.0.1\", port=5037)\n device = client.device(\"emulator-5554\")\n result = device.screencap()\n with open(\"screen.png\", \"wb\") as fp:\n fp.write(result)\n\nPush file or folder\n--------------------\n\n.. code-block:: python\n\n from ppadb.client import Client as AdbClient\n client = AdbClient(host=\"127.0.0.1\", port=5037)\n device = client.device(\"emulator-5554\")\n\n device.push(\"example.apk\", \"/sdcard/example.apk\")\n\nPull\n----\n\n.. code-block:: python\n\n from ppadb.client import Client as AdbClient\n client = AdbClient(host=\"127.0.0.1\", port=5037)\n device = client.device(\"emulator-5554\")\n\n device.shell(\"screencap -p /sdcard/screen.png\")\n device.pull(\"/sdcard/screen.png\", \"screen.png\")\n\nConnect to device\n-----------------\n\n.. code-block:: python\n\n from ppadb.client import Client as AdbClient\n client = AdbClient(host=\"127.0.0.1\", port=5037)\n client.remote_connect(\"172.20.0.1\", 5555)\n\n device = client.device(\"172.20.0.1:5555\")\n\n # Disconnect all devices\n client.remote_disconnect()\n\n ##Disconnect 172.20.0.1\n # client.remote_disconnect(\"172.20.0.1\")\n ##Or\n # client.remote_disconnect(\"172.20.0.1\", 5555)\n\n\nEnable debug logger\n--------------------\n\n.. code-block:: python\n\n logging.getLogger(\"ppadb\").setLevel(logging.DEBUG)\n\nAsync Client\n--------------------\n\n.. code-block:: python\n\n import asyncio\n import aiofiles\n from ppadb.client_async import ClientAsync as AdbClient\n\n async def _save_screenshot(device):\n result = await device.screencap()\n file_name = f\"{device.serial}.png\"\n async with aiofiles.open(f\"{file_name}\", mode='wb') as f:\n await f.write(result)\n\n return file_name\n\n async def main():\n client = AdbClient(host=\"127.0.0.1\", port=5037)\n devices = await client.devices()\n for device in devices:\n print(device.serial)\n\n result = await asyncio.gather(*[_save_screenshot(device) for device in devices])\n print(result)\n\n asyncio.run(main())\n\n\n\n\n\n\nHow to run test cases\n======================\n\nPrepare\n--------\n\n1. Install Docker\n\n2. Install Docker Compose\n\n.. code-block:: console\n\n pip install docker-compose\n\n3. Modify `test/conftest.py`\n\nChange the value of `adb_host` to the \"emulator\"\n\n.. code-block:: python\n\n adb_host=\"emulator\"\n\n4. Run testcases\n\n.. code-block:: console\n\n docker-compose up\n\nResult\n\n.. code-block:: console\n\n Starting purepythonadb_emulator_1 ... done\n Recreating purepythonadb_python_environment_1 ... done\n Attaching to purepythonadb_emulator_1, purepythonadb_python_environment_1\n emulator_1 | + echo n\n emulator_1 | + /home/user/android-sdk-linux/tools/bin/avdmanager create avd -k system-images;android-25;google_apis;x86 -n Docker -b x86 -g google_apis --device 8 --force\n Parsing /home/user/android-sdk-linux/emulator/package.xmlParsing /home/user/android-sdk-linux/patcher/v4/package.xmlParsing /home/user/android-sdk-linux/platform-tools/package.xmlParsing /home/user/android-sdk-linux/platforms/android-25/package.xmlParsing /home/user/android-sdk-linux/system-images/android-25/google_apis/x86/package.xmlParsing /home/user/android-sdk-linux/tools/package.xml+ echo hw.keyboard = true\n emulator_1 | + adb start-server\n emulator_1 | * daemon not running; starting now at tcp:5037\n python_environment_1 | ============================= test session starts ==============================\n python_environment_1 | platform linux -- Python 3.6.1, pytest-3.6.3, py-1.5.4, pluggy-0.6.0\n python_environment_1 | rootdir: /code, inifile:\n python_environment_1 | collected 27 items\n python_environment_1 |\n emulator_1 | * daemon started successfully\n emulator_1 | + exec /usr/bin/supervisord\n emulator_1 | /usr/lib/python2.7/dist-packages/supervisor/options.py:298: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a \"-c\" argument specifying an absolute path to a configuration file for improved security.\n emulator_1 | 'Supervisord is running as root and it is searching '\n emulator_1 | 2018-07-07 17:19:47,560 CRIT Supervisor running as root (no user in config file)\n emulator_1 | 2018-07-07 17:19:47,560 INFO Included extra file \"/etc/supervisor/conf.d/supervisord.conf\" during parsing\n emulator_1 | 2018-07-07 17:19:47,570 INFO RPC interface 'supervisor' initialized\n emulator_1 | 2018-07-07 17:19:47,570 CRIT Server 'unix_http_server' running without any HTTP authentication checking\n emulator_1 | 2018-07-07 17:19:47,570 INFO supervisord started with pid 1\n emulator_1 | 2018-07-07 17:19:48,573 INFO spawned: 'socat-5554' with pid 74\n emulator_1 | 2018-07-07 17:19:48,574 INFO spawned: 'socat-5555' with pid 75\n emulator_1 | 2018-07-07 17:19:48,576 INFO spawned: 'socat-5037' with pid 76\n emulator_1 | 2018-07-07 17:19:48,578 INFO spawned: 'novnc' with pid 77\n emulator_1 | 2018-07-07 17:19:48,579 INFO spawned: 'socat-9008' with pid 78\n emulator_1 | 2018-07-07 17:19:48,582 INFO spawned: 'emulator' with pid 80\n emulator_1 | 2018-07-07 17:19:49,607 INFO success: socat-5554 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)\n emulator_1 | 2018-07-07 17:19:49,607 INFO success: socat-5555 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)\n emulator_1 | 2018-07-07 17:19:49,607 INFO success: socat-5037 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)\n emulator_1 | 2018-07-07 17:19:49,607 INFO success: novnc entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)\n emulator_1 | 2018-07-07 17:19:49,608 INFO success: socat-9008 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)\n emulator_1 | 2018-07-07 17:19:49,608 INFO success: emulator entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)\n python_environment_1 | test/test_device.py .............. [ 51%]\n python_environment_1 | test/test_host.py .. [ 59%]\n python_environment_1 | test/test_host_serial.py ........ [ 88%]\n python_environment_1 | test/test_plugins.py ... [100%]\n python_environment_1 |\n python_environment_1 | ------------------ generated xml file: /code/test_result.xml -------------------\n python_environment_1 | ========================= 27 passed in 119.15 seconds ==========================\n purepythonadb_python_environment_1 exited with code 0\n Aborting on container exit...\n Stopping purepythonadb_emulator_1 ... done\n\nMore Information\n=================\n\nA pure Node.js client for the Android Debug Bridge\n---------------------------------------------------\n\nadbkit_\n\nADB documents\n--------------\n\n- protocol_\n- services_\n- sync_\n\n.. _adbkit: https://github.com/openstf/stf\n.. _protocol: https://android.googlesource.com/platform/system/core/+/master/adb/protocol.txt\n.. _services: https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT\n.. _sync: https://android.googlesource.com/platform/system/core/+/master/adb/SYNC.TXT\n.. _`google/python-adb`: https://github.com/google/python-adb\n\n\n0.2.1 (2019-10-14)\n--------------------\n\n* Fixes #21: Rename the package name from \"adb\" to \"ppadb\"\n* Fixes #23: Support push dir to device\n* Fixes #25: Don't call logging.basicConfig() in the module\n\n\n0.1.6 (2019-01-21)\n-------------------\n\n* Fix #4 push does not preserve original timestap unlike equiv adb push from command line\n* Fix #6 forward_list should also check serial\n* Fix #8: adb/command/host/__init__.py can take an exception parsing \"devices\" data\n\n\n0.1.0 (2018-06-23)\n-------------------\n\n* First release on PyPI.",
"bugtrack_url": null,
"license": "MIT license",
"summary": "Pure python implementation of the adb client",
"version": "0.3.0.dev0",
"project_urls": {
"Homepage": "https://github.com/Swind/pure-python-adb"
},
"split_keywords": [
"adb"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "0ab71c4d6b2cbe499b4180177abcf3ae2bb2d8b36acf695ae7d8e9eb99ba00ea",
"md5": "5b260d181a56e134a4e63db98485b170",
"sha256": "0ecc89d780160cfe03260ba26df2c471a05263b2cad0318363573ee8043fb94d"
},
"downloads": -1,
"filename": "pure-python-adb-0.3.0.dev0.tar.gz",
"has_sig": false,
"md5_digest": "5b260d181a56e134a4e63db98485b170",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 25680,
"upload_time": "2020-08-05T18:41:27",
"upload_time_iso_8601": "2020-08-05T18:41:27.157840Z",
"url": "https://files.pythonhosted.org/packages/0a/b7/1c4d6b2cbe499b4180177abcf3ae2bb2d8b36acf695ae7d8e9eb99ba00ea/pure-python-adb-0.3.0.dev0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2020-08-05 18:41:27",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Swind",
"github_project": "pure-python-adb",
"travis_ci": true,
"coveralls": false,
"github_actions": false,
"requirements": [],
"lcname": "pure-python-adb"
}