python-library-lan-router 0.1.0__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .venv/
8
+ .env
9
+ .env.*
10
+ !.env.example
11
+ # packages 示例本地密钥(*.example 为模板,可提交)
12
+ packages/**/examples/**/.env
13
+ !packages/**/examples/**/.env.example
14
+ packages/**/examples/**/mcp.json
15
+ !packages/**/examples/**/mcp.json.example
16
+ packages/**/examples/**/.sandbox/
17
+ .pytest_cache/
18
+ config.yaml
19
+ logs/
20
+ .cursor/
21
+ uv.lock
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-library-lan-router
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Requires-Python: >=3.10
5
5
  Requires-Dist: pydantic>=2.0.0
6
6
  Requires-Dist: tplinkrouterc6u>=0.1.0
@@ -8,4 +8,6 @@ class Device(BaseModel):
8
8
  mac: str
9
9
  """设备MAC地址"""
10
10
  type: str
11
- """设备类型"""
11
+ """设备类型"""
12
+ active: bool = True
13
+ """路由器报告的在线状态;未返回在线字段时视为在线"""
@@ -0,0 +1,53 @@
1
+ from tplinkrouterc6u import TPLinkXDRClient
2
+
3
+ from .base import BaseRouter
4
+ from .device import Device
5
+
6
+
7
+ class _TPLinkXDRClientNoProxy(TPLinkXDRClient):
8
+ """TP-Link 客户端;忽略 HTTP_PROXY 等环境变量,内网路由器应直连。"""
9
+
10
+ def __init__(self, *args, **kwargs) -> None:
11
+ super().__init__(*args, **kwargs)
12
+ self._session.trust_env = False
13
+
14
+
15
+ class TPLinkRouter(BaseRouter):
16
+ _router: TPLinkXDRClient | None = None
17
+
18
+ def model_post_init(self, ctx) -> None:
19
+ self._router = _TPLinkXDRClientNoProxy(
20
+ self.hostname,
21
+ self.username,
22
+ self.password,
23
+ )
24
+
25
+ def login(self):
26
+ self._router.authorize()
27
+
28
+ def logout(self):
29
+ self._router.logout()
30
+
31
+ def scan(self) -> list[Device]:
32
+ devices = []
33
+ status = self._router.get_status()
34
+
35
+ for data in status.devices:
36
+ type = getattr(data.type, "value", str(data.type))
37
+ name = data.hostname or ""
38
+ ip = self._show(data.ipaddr)
39
+ mac = self._show(data.macaddr)
40
+ device = Device(
41
+ name=name,
42
+ ip=ip,
43
+ mac=mac,
44
+ type=type,
45
+ active=data.active,
46
+ )
47
+ devices.append(device)
48
+
49
+ return devices
50
+
51
+ def _show(self, v: str | None) -> str:
52
+ """显示空值"""
53
+ return "-" if v is None or v == "" else v
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "python-library-lan-router"
7
- version = "0.1.0"
7
+ version = "0.1.2"
8
8
  requires-python = ">=3.10"
9
9
  dependencies = [
10
10
  "tplinkrouterc6u>=0.1.0",
@@ -0,0 +1,36 @@
1
+ import unittest
2
+
3
+ from lan_router import Device, create_router
4
+
5
+
6
+ class LanRouterTests(unittest.TestCase):
7
+ def test_create_router_rejects_unknown_vendor(self) -> None:
8
+ with self.assertRaises(ValueError) as ctx:
9
+ create_router("unknown") # type: ignore[arg-type]
10
+ self.assertIn("不支持", str(ctx.exception))
11
+
12
+ def test_device_model(self) -> None:
13
+ d = Device(
14
+ name="n",
15
+ ip="192.168.0.1",
16
+ mac="00:00:00:00:00:01",
17
+ type="wifi",
18
+ active=False,
19
+ )
20
+ self.assertEqual(d.name, "n")
21
+ self.assertEqual(d.ip, "192.168.0.1")
22
+ self.assertFalse(d.active)
23
+
24
+ def test_tplink_router_ignores_http_proxy_env(self) -> None:
25
+ router = create_router(
26
+ "tplink",
27
+ hostname="192.168.1.1",
28
+ username="admin",
29
+ password="secret",
30
+ )
31
+ assert router._router is not None
32
+ self.assertFalse(router._router._session.trust_env)
33
+
34
+
35
+ if __name__ == "__main__":
36
+ unittest.main()
@@ -1,11 +0,0 @@
1
- __pycache__/
2
- *.pyc
3
- *.pyo
4
- *.egg-info/
5
- dist/
6
- build/
7
- .venv/
8
- .env
9
- .pytest_cache/
10
- config.yaml
11
- logs/
@@ -1,33 +0,0 @@
1
- from .base import BaseRouter
2
- from .device import Device
3
- from tplinkrouterc6u import TPLinkXDRClient
4
-
5
- class TPLinkRouter(BaseRouter):
6
- _router: TPLinkXDRClient = None
7
-
8
- def model_post_init(self,ctx):
9
- self._router = TPLinkXDRClient(self.hostname, self.username, self.password)
10
-
11
- def login(self):
12
- self._router.authorize()
13
-
14
- def logout(self):
15
- self._router.logout()
16
-
17
- def scan(self) -> list[Device]:
18
- devices = []
19
- status = self._router.get_status()
20
-
21
- for data in status.devices:
22
- type = getattr(data.type, "value", str(data.type))
23
- name = data.hostname or ""
24
- ip = self._show(data.ipaddr)
25
- mac = self._show(data.macaddr)
26
- device = Device(name=name, ip=ip, mac=mac, type=type)
27
- devices.append(device)
28
-
29
- return devices
30
-
31
- def _show(self, v: str | None) -> str:
32
- """显示空值"""
33
- return "-" if v is None or v == "" else v
@@ -1,19 +0,0 @@
1
- import unittest
2
-
3
- from lan_router import Device, create_router
4
-
5
-
6
- class LanRouterTests(unittest.TestCase):
7
- def test_create_router_rejects_unknown_vendor(self) -> None:
8
- with self.assertRaises(ValueError) as ctx:
9
- create_router("unknown") # type: ignore[arg-type]
10
- self.assertIn("不支持", str(ctx.exception))
11
-
12
- def test_device_model(self) -> None:
13
- d = Device(name="n", ip="192.168.0.1", mac="00:00:00:00:00:01", type="wifi")
14
- self.assertEqual(d.name, "n")
15
- self.assertEqual(d.ip, "192.168.0.1")
16
-
17
-
18
- if __name__ == "__main__":
19
- unittest.main()