Skip to content

Commit 6ce25a5

Browse files
committed
feat: show version on web page
1 parent 8dd3954 commit 6ce25a5

File tree

13 files changed

+157
-83
lines changed

13 files changed

+157
-83
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
# ui-viewer
2+
[![github actions](https://github.com/codematrixer/ui-viewer/actions/workflows/release.yml/badge.svg)](https://github.com/codematrixer/ui-viewer/actions)
3+
[![pypi version](https://img.shields.io/pypi/v/uiviewer.svg)](https://pypi.python.org/pypi/uiviewer)
4+
![python](https://img.shields.io/pypi/pyversions/uiviewer.svg)
5+
26
UI hierarchy visualization tool, supporting Android, iOS, HarmonyOS NEXT.
37

48
![showcase](./docs/imgs/show.gif)
59

610
# Installation
11+
- python3.8+
12+
713
```shell
814
pip3 install -U uiviewer
915
```

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "uiviewer"
3-
version = "1.0.0"
3+
version = "1.0.1"
44
description = "UI hierarchy visualization tool, supporting Android, iOS, HarmonyOS NEXT."
55
authors = ["codematrixer <chenli_gogo@163.com>"]
66
license = "MIT"

uiviewer/__init__.py

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1 @@
1-
# -*- coding: utf-8 -*-
2-
3-
import logging
4-
5-
formatter = logging.Formatter('[%(asctime)s] %(filename)15s[line:%(lineno)4d] \
6-
[%(levelname)s] %(message)s',
7-
datefmt='%Y-%m-%d %H:%M:%S')
8-
9-
logger = logging.getLogger('hmdriver2')
10-
logger.setLevel(logging.DEBUG)
11-
12-
console_handler = logging.StreamHandler()
13-
console_handler.setLevel(logging.DEBUG)
14-
console_handler.setFormatter(formatter)
15-
16-
logger.addHandler(console_handler)
17-
18-
19-
__all__ = ['logger']
1+
# -*- coding: utf-8 -*-

uiviewer/__main__.py

Lines changed: 6 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,12 @@
44
import webbrowser
55
import uvicorn
66
import threading
7-
from typing import Union, Optional
87

9-
from fastapi import FastAPI, Request, Query, HTTPException
8+
from fastapi import FastAPI, Request, HTTPException
109
from fastapi.staticfiles import StaticFiles
11-
from fastapi.responses import JSONResponse, RedirectResponse
12-
13-
from uiviewer._device import (
14-
list_serials,
15-
init_device,
16-
cached_devices,
17-
AndroidDevice,
18-
IosDevice,
19-
HarmonyDevice
20-
)
10+
from fastapi.responses import JSONResponse
11+
12+
from uiviewer.routers import api
2113
from uiviewer._models import ApiResponse
2214

2315

@@ -29,6 +21,8 @@
2921

3022
app.mount("/static", StaticFiles(directory=static_dir), name="static")
3123

24+
app.include_router(api.router)
25+
3226

3327
@app.exception_handler(Exception)
3428
def global_exception_handler(request: Request, exc: Exception):
@@ -50,42 +44,6 @@ def open_browser(port):
5044
webbrowser.open_new(f"http://127.0.0.1:{port}")
5145

5246

53-
@app.get("/")
54-
def root():
55-
return RedirectResponse(url="/static/index.html")
56-
57-
58-
@app.get("/health")
59-
def health():
60-
return "ok"
61-
62-
63-
@app.get("/{platform}/serials", response_model=ApiResponse)
64-
def get_serials(platform: str):
65-
serials = list_serials(platform)
66-
return ApiResponse.doSuccess(serials)
67-
68-
69-
@app.post("/{platform}/{serial}/connect", response_model=ApiResponse)
70-
def connect(platform: str, serial: str, wdaUrl: Optional[str] = Query(None), maxDepth: Optional[int] = Query(None)):
71-
ret = init_device(platform, serial, wdaUrl, maxDepth)
72-
return ApiResponse.doSuccess(ret)
73-
74-
75-
@app.get("/{platform}/{serial}/screenshot", response_model=ApiResponse)
76-
def screenshot(platform: str, serial: str):
77-
device: Union[AndroidDevice, IosDevice, HarmonyDevice] = cached_devices.get((platform, serial))
78-
data = device.take_screenshot()
79-
return ApiResponse.doSuccess(data)
80-
81-
82-
@app.get("/{platform}/{serial}/hierarchy", response_model=ApiResponse)
83-
def dump_hierarchy(platform: str, serial: str):
84-
device: Union[AndroidDevice, IosDevice, HarmonyDevice] = cached_devices.get((platform, serial))
85-
data = device.dump_hierarchy()
86-
return ApiResponse.doSuccess(data)
87-
88-
8947
def run(port=8000):
9048
timer = threading.Timer(1.0, open_browser, args=[port])
9149
timer.daemon = True

uiviewer/_device.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import abc
44
import tempfile
5-
from typing import List, Dict, Union, Tuple
5+
from typing import List, Dict, Union, Tuple, Optional
66
from functools import cached_property # python3.8+
77

88
from PIL import Image
@@ -101,9 +101,13 @@ class IosDevice(DeviceMeta):
101101
def __init__(self, udid: str, wda_url: str, max_depth: int) -> None:
102102
self.udid = udid
103103
self.wda_url = wda_url
104-
self.max_depth = max_depth
104+
self._max_depth = max_depth
105105
self.client = wda.Client(wda_url)
106106

107+
@property
108+
def max_depth(self) -> int:
109+
return int(self._max_depth) if self._max_depth else 30
110+
107111
@cached_property
108112
def scale(self) -> int:
109113
return self.client.scale
@@ -152,7 +156,7 @@ def get_device(platform: str, serial: str, wda_url: str, max_depth: int) -> Unio
152156
cached_devices = {}
153157

154158

155-
def init_device(platform: str, serial: str, wda_url: str = None, max_depth: int = 30) -> bool:
159+
def init_device(platform: str, serial: str, wda_url: str, max_depth: int):
156160

157161
if serial not in list_serials(platform):
158162
raise HTTPException(status_code=500, detail=f"Device<{serial}> not found")

uiviewer/_error.py

Lines changed: 0 additions & 4 deletions
This file was deleted.

uiviewer/_logger.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import logging
4+
5+
formatter = logging.Formatter('[%(asctime)s] %(filename)15s[line:%(lineno)4d] \
6+
[%(levelname)s] %(message)s',
7+
datefmt='%Y-%m-%d %H:%M:%S')
8+
9+
logger = logging.getLogger('hmdriver2')
10+
logger.setLevel(logging.DEBUG)
11+
12+
console_handler = logging.StreamHandler()
13+
console_handler.setLevel(logging.DEBUG)
14+
console_handler.setFormatter(formatter)
15+
16+
logger.addHandler(console_handler)
17+
18+
19+
__all__ = ['logger']

uiviewer/_version.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import importlib.metadata
4+
5+
__version__ = importlib.metadata.version('uiviewer')

uiviewer/routers/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# -*- coding: utf-8 -*-

uiviewer/routers/api.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from typing import Union, Optional
4+
5+
from fastapi import APIRouter, Query
6+
from fastapi.responses import RedirectResponse
7+
8+
from uiviewer._device import (
9+
list_serials,
10+
init_device,
11+
cached_devices,
12+
AndroidDevice,
13+
IosDevice,
14+
HarmonyDevice
15+
)
16+
from uiviewer._models import ApiResponse
17+
from uiviewer._version import __version__
18+
19+
20+
router = APIRouter()
21+
22+
23+
@router.get("/")
24+
def root():
25+
return RedirectResponse(url="/static/index.html")
26+
27+
28+
@router.get("/health")
29+
def health():
30+
return "ok"
31+
32+
33+
@router.get("/version", response_model=ApiResponse)
34+
def get_version():
35+
return ApiResponse.doSuccess(__version__)
36+
37+
38+
@router.get("/{platform}/serials", response_model=ApiResponse)
39+
def get_serials(platform: str):
40+
serials = list_serials(platform)
41+
return ApiResponse.doSuccess(serials)
42+
43+
44+
@router.post("/{platform}/{serial}/connect", response_model=ApiResponse)
45+
def connect(
46+
platform: str,
47+
serial: str,
48+
wdaUrl: Union[str, None] = Query(None),
49+
maxDepth: Union[int, None] = Query(None)
50+
):
51+
ret = init_device(platform, serial, wdaUrl, maxDepth)
52+
return ApiResponse.doSuccess(ret)
53+
54+
55+
@router.get("/{platform}/{serial}/screenshot", response_model=ApiResponse)
56+
def screenshot(platform: str, serial: str):
57+
device: Union[AndroidDevice, IosDevice, HarmonyDevice] = cached_devices.get((platform, serial))
58+
data = device.take_screenshot()
59+
return ApiResponse.doSuccess(data)
60+
61+
62+
@router.get("/{platform}/{serial}/hierarchy", response_model=ApiResponse)
63+
def dump_hierarchy(platform: str, serial: str):
64+
device: Union[AndroidDevice, IosDevice, HarmonyDevice] = cached_devices.get((platform, serial))
65+
data = device.dump_hierarchy()
66+
return ApiResponse.doSuccess(data)

0 commit comments

Comments
 (0)