diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index b3ad0fa..bd70239 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -33,4 +33,8 @@ jobs: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALL_SECRET }} run: | pip install coveralls - coveralls \ No newline at end of file + coveralls + - name: Static type checking + run: | + pip install mypy + mypy \ No newline at end of file diff --git a/localite/__init__.py b/localite/__init__.py index de74a3d..94bfac3 100644 --- a/localite/__init__.py +++ b/localite/__init__.py @@ -1,2 +1,2 @@ -__path__ = __import__("pkgutil").extend_path(__path__, __name__) +# __path__ = __import__("pkgutil").extend_path(__path__, __name__) diff --git a/localite/coil.py b/localite/coil.py index c28e3f8..d35c451 100644 --- a/localite/coil.py +++ b/localite/coil.py @@ -58,7 +58,7 @@ def __init__(self, coil: int = 0, address: Tuple[str, int] = ("127.0.0.1", 6667) def await_connection(self): print("[", end="") - while not self.connected: + while not self.connected: # pragma no cover print(".", end="") print("]") @@ -203,3 +203,18 @@ def mode(self) -> str: """ return self.request("stimulator_mode")["name"] + + def set_response( + self, mepmaxtime: float, mepamplitude: float, mepmin: float, mepmax: float + ): + key = f"coil_{self.id}_response" + msg = { + key: { + "mepmaxtime": mepmaxtime, + "mepamplitude": mepamplitude, + "mepmin": mepmin, + "mepmax": mepmax, + } + } + self._push_loc(msg=json.dumps(msg)) + diff --git a/localite/flow/loc.py b/localite/flow/loc.py index e3031ed..8cfc5e6 100644 --- a/localite/flow/loc.py +++ b/localite/flow/loc.py @@ -126,7 +126,6 @@ def close(self) -> None: def write(self, msg: str) -> None: self.socket.sendall(msg.encode("ascii")) - return self def read(self) -> Union[None, str]: "parse the message" @@ -134,10 +133,10 @@ def read(self) -> Union[None, str]: while True: try: prt = self.socket.recv(1) - bmsg += prt + bmsg += prt dec = bmsg.decode("ascii") return json.dumps(json.loads(dec)) - except json.JSONDecodeError: # pragma no cover + except json.JSONDecodeError: # pragma no cover pass except Exception as e: # pragma no cover print("LCL:EXC:", e) @@ -161,7 +160,7 @@ def listen_and_queue( """listen to the localice stream and forward to queue """ msg = client.listen() - if json.loads(msg) in ignore or None: + if msg is None or json.loads(msg) in ignore: return None else: print("LOC:MSG", msg) @@ -175,12 +174,12 @@ class LastMessage(Payload): def __init__(self): self.reset() - + def reset(self): self.expect = None self.counter = 0 self.msg = "" - + def update(self, payload: Payload): "update the expectation" if payload.fmt != "loc": # pragma no cover @@ -223,6 +222,7 @@ def expects(self, response: Union[Dict[str, Any], None]) -> int: print("LOC:FOUND", response) self.reset() return 0 + return 0 class LOC(threading.Thread): @@ -255,23 +255,23 @@ def run(self): while self.is_running.is_set(): try: payload = get_from_queue(self.inbox) - if payload is None: + if payload is None: if "status" in lastmessage.msg: response = listen_and_queue( client, ignore=[], queue=self.outbox ) - else: + else: response = listen_and_queue( client, ignore=self.ignore, queue=self.outbox ) flevel = lastmessage.expects(response) - #print("LOC:FRUST", flevel, response) -# if flevel: -# print("LOC:FRUST", flevel, response) -# if flevel >= 2: -# print("LOC:RESEND", lastmessage.msg) -# client.send(lastmessage.msg) -# lastmessage.counter = 0 + # print("LOC:FRUST", flevel, response) + # if flevel: + # print("LOC:FRUST", flevel, response) + # if flevel >= 2: + # print("LOC:RESEND", lastmessage.msg) + # client.send(lastmessage.msg) + # lastmessage.counter = 0 else: print("LOC:RECV", payload) if payload.fmt == "cmd": diff --git a/localite/flow/mock.py b/localite/flow/mock.py index 0b3a5a0..4ca4eac 100644 --- a/localite/flow/mock.py +++ b/localite/flow/mock.py @@ -2,7 +2,7 @@ import json import threading import time -from typing import Dict, Union +from typing import Dict, Union, Any from localite.flow.payload import Queue from localite.flow.loc import localiteClient @@ -49,8 +49,7 @@ def Messages(): def kill(host: str = "127.0.0.1", port=6666): client = localiteClient(host, port) - msg = {"cmd": "poison-pill"} - msg = json.dumps(msg) + msg = json.dumps({"cmd": "poison-pill"}) client.send(msg) @@ -128,7 +127,7 @@ def kill(host: str = "127.0.0.1", port=6666): } -def create_response(msg: Dict[str, Union[str, int]]) -> Dict: +def create_response(msg: Any) -> Union[Dict, None]: if msg is None: return None key = list(msg.keys())[0] @@ -143,10 +142,13 @@ def create_response(msg: Dict[str, Union[str, int]]) -> Dict: "coil_0_target_index", "coil_1_target_index", ]: # set target index - if type(val) == int and val > 0: + if type(val) is int and val > 0: return msg else: - return {"error": msg} + return { + "request": {key: val}, + "reason": f"Index value out of range. Value: {val}, Range: [0..0]", + } elif key == "single_pulse": # trigger if val in ["COIL_0", "COIL_1"]: return {val.lower() + "_didt": 11} @@ -199,7 +201,7 @@ def await_running(self): pass @staticmethod - def read_msg(client: socket.socket) -> dict: + def read_msg(client: socket.socket) -> Union[Dict, None]: "parse the message" client.settimeout(0.1) msg = b" " @@ -207,8 +209,8 @@ def read_msg(client: socket.socket) -> dict: try: prt = client.recv(1) msg += prt - msg = json.loads(msg.decode("ascii")) - return msg + dmsg = json.loads(msg.decode("ascii")) + return dmsg except json.JSONDecodeError: # pragma no cover pass except socket.timeout: diff --git a/localite/flow/mrk.py b/localite/flow/mrk.py index f2d0885..723e490 100644 --- a/localite/flow/mrk.py +++ b/localite/flow/mrk.py @@ -38,12 +38,12 @@ def get_as_list(self) -> List[Any]: def expectation(msg: str) -> str: - msg = json.loads(msg) - key = list(msg.keys())[0] + dmsg = json.loads(msg) + key = list(dmsg.keys())[0] if key == "get": - return msg["get"] + return dmsg["get"] elif "single_pulse" in key: - return msg["single_pulse"].lower() + "_didt" + return dmsg["single_pulse"].lower() + "_didt" else: return key diff --git a/mypy.ini b/mypy.ini index 422ac89..8d41dc5 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,2 +1,6 @@ [mypy] mypy_path=/media/rgugg/tools/python3/pyliesl, /media/rgugg/tools/python3/pyreiz +ignore_missing_imports = True +files = localite/**/*.py +pretty = True +error_summary = True \ No newline at end of file diff --git a/test/flow/test_mock.py b/test/flow/test_mock.py index 08be44a..7c60e48 100644 --- a/test/flow/test_mock.py +++ b/test/flow/test_mock.py @@ -31,8 +31,8 @@ def test_create_response(): assert "error" in cr({"current_instrument": "GARBAGE"}).keys() assert "NONE" in cr({"current_instrument": "NONE"}).values() assert 1 in cr({"coil_0_target_index": 1}).values() - assert "error" in cr({"coil_0_target_index": -1}).keys() - assert "error" in cr({"coil_0_target_index": "T"}).keys() + assert "reason" in cr({"coil_0_target_index": -1}).keys() + assert "reason" in cr({"coil_0_target_index": "T"}).keys() assert "coil_0_didt" in cr({"single_pulse": "COIL_0"}).keys() assert "error" in cr({"single_pulse": "COIL_2"}).keys() assert 1 in cr({"coil_0_amplitude": 1}).values() diff --git a/test/test_coil.py b/test/test_coil.py index 814597c..bdf9e43 100644 --- a/test/test_coil.py +++ b/test/test_coil.py @@ -50,9 +50,10 @@ def test_coil_static_properties(coil): assert coil.temperature == 35 assert coil.didt == 99 assert coil.visible - assert coil.connected == True + assert coil.connected is True with raises(AttributeError): coil.connected = False + assert coil.position_reached is True assert coil.model == "Mock0704 mock" def test_coil_setable_properties(coil): @@ -80,6 +81,9 @@ def test_coil_setable_properties(coil): with raises(ValueError): coil.id = -1 + def test_coil_response(coil): + coil.set_response(mepmaxtime=18, mepamplitude=40, mepmin=-20, mepmax=20) + def test_coil_trigger(coil): coil.trigger()