Dmitry Telenkov 1 kuukausi sitten
vanhempi
commit
f61306be83

+ 38 - 0
python_net/aioarp/aioarp/_backends/_async.py

@@ -0,0 +1,38 @@
+import select
+import socket
+import typing
+
+import anyio
+
+from aioarp import _exceptions as exc
+
+from ._base import SocketInterface
+
+
+class AsyncStream:
+
+    def __init__(self,
+                 interface: str,
+                 sock: typing.Optional[SocketInterface] = None
+                 ):
+        self.sock: SocketInterface
+        if not sock:
+            self.sock = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003)) # type: ignore
+        else:
+            self.sock = sock
+        self.sock.bind((interface, 0))
+
+    async def receive_frame(self, timeout: float) -> bytes:
+        frame: typing.Optional[bytes]
+        with anyio.move_on_after(timeout):
+            while True:
+                r, _, _ = select.select([self.sock], [], [], 0.00001)
+                if r:
+                    frame = self.sock.recv(1123123)
+                    break
+                await anyio.sleep(0)
+        if not frame:
+            raise exc.ReadTimeoutError()
+        return frame
+    
+    

+ 58 - 0
python_net/aioarp/aioarp/_backends/_sync.py

@@ -0,0 +1,58 @@
+import socket
+import typing
+
+from aioarp import _exceptions as exc
+from aioarp._backends._base import SocketInterface
+
+
+__all__ = (
+    'Stream',
+)
+
+class Stream:
+
+    def __init__(self,
+                 interface: str,
+                 sock: typing.Optional[SocketInterface] = None
+                 ):
+        self.sock: SocketInterface
+        if not sock:
+            self.sock = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003)) # type: ignore
+        else:
+            self.sock = sock
+        self.sock.bind((interface, 0))
+        
+    def receive_frame(self, timeout: float) -> bytes:
+        self.sock.settimeout(timeout)
+        try:
+            frame = self.sock.recv(1123123)
+        except socket.timeout:
+            raise exc.ReadTimeoutError()
+        return frame
+    
+    def write_frame(self, frame: bytes, timeout: float) -> None:
+        self.sock.settimeout(timeout)
+        try:
+            self.sock.sendall(frame)
+        except socket.timeout:
+            raise exc.WriteTimeoutError()
+        
+    def close(self) -> None:
+        self.sock.close()
+
+    def __enter__(self) -> "Stream":
+        return self
+    
+    def __exit__(self, exc_type: typing.Any, exc_val: typing.Any, exc_tb: typing.Any) -> None:
+        self.close()
+
+    async def __aenter__(self) -> "Stream":
+        return self
+    
+    async def __aexit__(self,
+                        exc_type: typing.Any,
+                        exc_val: typing.Any,
+                        exc_tb: typing.Any) -> None:
+        self.close()
+    
+

+ 27 - 0
python_net/aioarp/aioarp/_exceptions.py

@@ -0,0 +1,27 @@
+
+__all__ = (
+    'AioArpError',
+    'InvalidIpError',
+    'NotFoundError',
+    'TimeoutError',
+    'ReadTimeoutError'
+)
+
+
+class AioArpError(Exception):
+    ...
+
+class InvalidIpError(AioArpError):
+    ...
+
+class NotFoundError(AioArpError):
+    ...
+
+class TimeoutError(AioArpError):
+    ...
+
+class ReadTimeoutError(TimeoutError):
+    ...
+
+class WriteTimeoutError(TimeoutError):
+    ...

+ 1 - 0
python_net/aioarp/pyproject.toml

@@ -5,5 +5,6 @@ description = "Add your description here"
 readme = "README.md"
 requires-python = ">=3.13"
 dependencies = [
+    "anyio>=4.9.0",
     "getmac==0.9.5",
 ]

+ 4 - 1
python_net/aioarp/requirements.txt

@@ -1 +1,4 @@
-getmac==0.9.5
+anyio==4.9.0
+getmac==0.9.5
+idna==3.10
+sniffio==1.3.1

+ 36 - 1
python_net/aioarp/uv.lock

@@ -7,11 +7,28 @@ name = "aioarp"
 version = "0.1.0"
 source = { virtual = "." }
 dependencies = [
+    { name = "anyio" },
     { name = "getmac" },
 ]
 
 [package.metadata]
-requires-dist = [{ name = "getmac", specifier = "==0.9.5" }]
+requires-dist = [
+    { name = "anyio", specifier = ">=4.9.0" },
+    { name = "getmac", specifier = "==0.9.5" },
+]
+
+[[package]]
+name = "anyio"
+version = "4.9.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+    { name = "idna" },
+    { name = "sniffio" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949 }
+wheels = [
+    { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916 },
+]
 
 [[package]]
 name = "getmac"
@@ -21,3 +38,21 @@ sdist = { url = "https://files.pythonhosted.org/packages/89/a8/4af8e06912cd83b1c
 wheels = [
     { url = "https://files.pythonhosted.org/packages/18/85/4cdbc925381422397bd2b3280680e130091173f2c8dfafb9216eaaa91b00/getmac-0.9.5-py2.py3-none-any.whl", hash = "sha256:22b8a3e15bc0c6bfa94651a3f7f6cd91b59432e1d8199411d4fe12804423e0aa", size = 35781 },
 ]
+
+[[package]]
+name = "idna"
+version = "3.10"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 }
+wheels = [
+    { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
+]
+
+[[package]]
+name = "sniffio"
+version = "1.3.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 }
+wheels = [
+    { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
+]