diff --git a/src/isar/config/settings.py b/src/isar/config/settings.py index 43204cbf..66fef7f0 100644 --- a/src/isar/config/settings.py +++ b/src/isar/config/settings.py @@ -56,23 +56,27 @@ class Settings(BaseSettings): # Determines which mission planner module is used by ISAR # Options: [local echo] - # Selecting a different mission planner module than local may require certain access rights + # Selecting a different mission planner module than local may require certain access + # rights MISSION_PLANNER: str = Field(default="local") # Determines which storage modules are used by ISAR - # Comma separated list of modules to use. Each module will be called when storing results from inspections + # Comma separated list of modules to use. Each module will be called when storing + # results from inspections # Options [local blob slimm] # Selecting a different storage module than local may require certain access rights STORAGE: List[str] = Field(default=["local"]) # Determines whether the MQTT publishing module should be enabled or not - # The publishing module will attempt to connect to the MQTT broker configured in "service_connections" + # The publishing module will attempt to connect to the MQTT broker configured in + # "service_connections" # Options: [false true] MQTT_ENABLED: bool = Field(default=False) # Determines whether authentication is enabled for the API or not # Enabling this requires certain resources available for OAuth2 authentication - # Currently supported authentication is Azure AD (https://github.com/Intility/fastapi-azure-auth) + # Currently supported authentication is Azure AD + # (https://github.com/Intility/fastapi-azure-auth) AUTHENTICATION_ENABLED: bool = Field(default=False) # Tenant ID for the Azure tenant with your Azure Active Directory application @@ -139,11 +143,12 @@ class Settings(BaseSettings): default="https://slimmingestapidev.azurewebsites.net/api/Ingest" ) - # Whether the results should be copied directly into the SLIMM datalake or only the metadata + # Whether the results should be copied directly into the SLIMM datalake or only the + # metadata COPY_FILES_TO_SLIMM_DATALAKE: bool = Field(default=False) - # The configuration of this section is tightly coupled with the metadata that is submitted with the results once - # they have been uploaded. + # The configuration of this section is tightly coupled with the metadata that is + # submitted with the results once they have been uploaded. # Four digit code indicating facility PLANT_CODE: str = Field(default="1320") diff --git a/src/isar/mission_planner/echo_planner.py b/src/isar/mission_planner/echo_planner.py index 8a329faf..30325062 100644 --- a/src/isar/mission_planner/echo_planner.py +++ b/src/isar/mission_planner/echo_planner.py @@ -122,8 +122,8 @@ def _create_inspection_tasks_from_sensor_types( def _get_robot_pose(self, tag_name: str) -> Pose: """ - Retrieve robot pose corresponding to inspection of a given tag. For now, this is a temporary hard-coded - solution. + Retrieve robot pose corresponding to inspection of a given tag. For now, this is + a temporary hard-coded solution. """ predefined_pose: Pose = predefined_poses[tag_name] diff --git a/src/isar/models/communication/queues/queue_io.py b/src/isar/models/communication/queues/queue_io.py index a2f57298..ec286254 100644 --- a/src/isar/models/communication/queues/queue_io.py +++ b/src/isar/models/communication/queues/queue_io.py @@ -3,8 +3,8 @@ class QueueIO: """ - Creates input and output queue. The queues are defined such that input is from api to state machine - while output is from state machine to api. + Creates input and output queue. The queues are defined such that the input is from + api to state machine while the output is from state machine to api. """ def __init__(self, input_size: int = 0, output_size: int = 0): diff --git a/src/isar/models/mission.py b/src/isar/models/mission.py index 22336df6..df7b0a22 100644 --- a/src/isar/models/mission.py +++ b/src/isar/models/mission.py @@ -36,7 +36,10 @@ def _set_unique_id(self) -> None: plant_short_name: str = settings.PLANT_SHORT_NAME robot_id: str = settings.ROBOT_ID now: datetime = datetime.utcnow() - self.id = f"{plant_short_name.upper()}{robot_id.upper()}{now.strftime('%d%m%Y%H%M%S%f')[:-3]}" + self.id = ( + f"{plant_short_name.upper()}{robot_id.upper()} " + f"{now.strftime('%d%m%Y%H%M%S%f')[:-3]}" + ) def __post_init__(self) -> None: if self.id is None: diff --git a/src/isar/services/service_connections/mqtt/mqtt_client.py b/src/isar/services/service_connections/mqtt/mqtt_client.py index 7c20d808..4df217b1 100644 --- a/src/isar/services/service_connections/mqtt/mqtt_client.py +++ b/src/isar/services/service_connections/mqtt/mqtt_client.py @@ -58,7 +58,8 @@ def __init__(self, mqtt_queue: Queue) -> None: password = os.environ["ISAR_MQTT_PASSWORD"] except KeyError: self.logger.warning( - "Failed to retrieve ISAR_MQTT_PASSWORD from environment. Attempting with empty string as password." + "Failed to retrieve ISAR_MQTT_PASSWORD from environment. Attempting " + "with empty string as password." ) self.host: str = settings.MQTT_HOST @@ -110,7 +111,7 @@ def _on_backoff(data: dict) -> None: @staticmethod def _on_giveup(data: dict) -> None: logging.getLogger("mqtt_client").error( - "Failed to connect to MQTT Broker within set backoff strategy. Raising error." + "Failed to connect to MQTT Broker within set backoff strategy." ) @backoff.on_exception( diff --git a/src/isar/services/utilities/json_service.py b/src/isar/services/utilities/json_service.py index 4213765f..16c9c87f 100644 --- a/src/isar/services/utilities/json_service.py +++ b/src/isar/services/utilities/json_service.py @@ -21,7 +21,7 @@ def to_object(json_string: str) -> SimpleNamespace: class EnhancedJSONEncoder(json.JSONEncoder): """ - Custom JSONEncoder used in this project. Of special note is the ability to encode dataclasses. + Custom JSONEncoder with the ability to encode dataclasses. """ def default(self, o): diff --git a/src/isar/services/utilities/queue_utilities.py b/src/isar/services/utilities/queue_utilities.py index 293643f8..e715c28a 100644 --- a/src/isar/services/utilities/queue_utilities.py +++ b/src/isar/services/utilities/queue_utilities.py @@ -15,8 +15,9 @@ class QueueUtilities: @staticmethod def check_queue(queue: Queue, queue_timeout: int = None) -> Any: """ - Checks if there is a message on a queue. If a timeout is specified the function will raise a QueueTimeoutError - if there is no message within the timeout. If there is no timeout specified this function will block. + Checks if there is a message on a queue. If a timeout is specified the function + will raise a QueueTimeoutError if there is no message within the timeout. If + there is no timeout specified this function will block. :param queue: The queue to be checked for a message :param queue_timeout: Timeout in seconds :return: Message found on queue diff --git a/src/isar/services/utilities/scheduling_utilities.py b/src/isar/services/utilities/scheduling_utilities.py index 82ceb39e..fef28a03 100644 --- a/src/isar/services/utilities/scheduling_utilities.py +++ b/src/isar/services/utilities/scheduling_utilities.py @@ -17,8 +17,8 @@ class SchedulingUtilities: """ - Contains utility functions for scheduling missions from the API. The class handles required thread communication - through queues to the state machine. + Contains utility functions for scheduling missions from the API. The class handles + required thread communication through queues to the state machine. """ @inject @@ -31,9 +31,10 @@ def ready_to_start_mission( self, ) -> Tuple[bool, Optional[Tuple[StartMessage, HTTPStatus]]]: """ - Checks the current mission status by communicating with the state machine thread through queues. - :return: (True, None) if the mission may be started. Otherwise (False, response) with a relevant response - message indicating the cause. + Checks the current mission status by communicating with the state machine thread + through queues. + :return: (True, None) if the mission may be started. Otherwise (False, response) + with a relevant response message indicating the cause. """ self.queues.mission_status.input.put(True) try: @@ -58,7 +59,8 @@ def start_mission(self, mission: Mission) -> Tuple[StartMessage, HTTPStatus]: """ Starts a mission by communicating with the state machine thread through queues. :param mission: A Mission containing the mission tasks to be started. - :return: (message, status_code) is returned indicating the success and cause of the operation. + :return: (message, status_code) is returned indicating the success and cause of + the operation. """ self.queues.start_mission.input.put(deepcopy(mission)) try: diff --git a/src/isar/state_machine/state_machine.py b/src/isar/state_machine/state_machine.py index 8d872c05..f7d01e28 100644 --- a/src/isar/state_machine/state_machine.py +++ b/src/isar/state_machine/state_machine.py @@ -300,7 +300,8 @@ def log_task_overview(self, mission: Mission): """Log an overview of the tasks in a mission""" task_status: str = "\n".join( [ - f"{i:>3} {type(task).__name__:<20} {str(task.id)[:8]:<32} -- {task.status}" + f"{i:>3} {type(task).__name__:<20} " + f"{str(task.id)[:8]:<32} -- {task.status}" for i, task in enumerate(mission.tasks) ] ) diff --git a/src/isar/state_machine/states/initiate_task.py b/src/isar/state_machine/states/initiate_task.py index 75b118cd..0ec58d3c 100644 --- a/src/isar/state_machine/states/initiate_task.py +++ b/src/isar/state_machine/states/initiate_task.py @@ -95,7 +95,8 @@ def _run(self): except RobotInvalidTaskExpection: self.state_machine.current_task.status = TaskStatus.Failed self.logger.warning( - f"Failed to initiate {type(self.state_machine.current_task).__name__}" + f"Failed to initiate " + f"{type(self.state_machine.current_task).__name__}" f"Invalid task: {str(self.state_machine.current_task.id)[:8]}" ) next_state = States.InitiateTask @@ -107,14 +108,16 @@ def _run(self): self.state_machine.current_task.status = TaskStatus.Scheduled next_state = States.Monitor self.logger.info( - f"Successfully initiated {type(self.state_machine.current_task).__name__} " + f"Successfully initiated " + f"{type(self.state_machine.current_task).__name__} " f"task: {str(self.state_machine.current_task.id)[:8]}" ) break else: self.initiate_task_failure_counter += 1 self.logger.info( - f"Initiating task failed #: {str(self.initiate_task_failure_counter)}" + f"Initiating task failed #: " + f"{str(self.initiate_task_failure_counter)}" ) if ( self.initiate_task_failure_counter diff --git a/src/isar/storage/local_storage.py b/src/isar/storage/local_storage.py index e9e1756e..db44cc65 100644 --- a/src/isar/storage/local_storage.py +++ b/src/isar/storage/local_storage.py @@ -34,7 +34,8 @@ def store(self, inspection: Inspection, metadata: MissionMetadata): metadata_file.write(metadata_bytes) except IOError as e: self.logger.warning( - f"Failed open/write for one of the following files: \n{absolute_path}\n{absolute_metadata_path}" + f"Failed open/write for one of the following files: \n" + f"{absolute_path}\n{absolute_metadata_path}" ) raise StorageException from e except Exception as e: diff --git a/src/isar/storage/slimm_storage.py b/src/isar/storage/slimm_storage.py index 06e03f41..af4dcb52 100644 --- a/src/isar/storage/slimm_storage.py +++ b/src/isar/storage/slimm_storage.py @@ -70,7 +70,8 @@ def _ingest(self, inspection, multiform_body, request_url, token): ) except (RequestException, HTTPError) as e: self.logger.warning( - f"Failed to upload inspection: {inspection.id} to SLIMM due to a request exception" + f"Failed to upload inspection: {inspection.id} to SLIMM due to a " + f"request exception" ) raise StorageException from e diff --git a/src/isar/storage/uploader.py b/src/isar/storage/uploader.py index 9c5a81d8..ad64b98c 100644 --- a/src/isar/storage/uploader.py +++ b/src/isar/storage/uploader.py @@ -99,15 +99,16 @@ def _upload(self, upload_item: UploaderQueueItem): upload_item.increment_retry(self.max_wait_time) self.logger.warning( f"Storage handler: {type(upload_item.storage_handler).__name__} " - f"failed to upload inspection: {str(upload_item.inspection.id)[:8]}. " + f"failed to upload inspection: " + f"{str(upload_item.inspection.id)[:8]}. " f"Retrying in {upload_item.seconds_until_retry()}s." ) else: self._internal_upload_queue.remove(upload_item) self.logger.error( f"Storage handler: {type(upload_item.storage_handler).__name__} " - f"exceeded max retries to upload inspection: {str(upload_item.inspection.id)[:8]}. " - "Aborting upload." + f"exceeded max retries to upload inspection: " + f"{str(upload_item.inspection.id)[:8]}. Aborting upload." ) def _process_upload_queue(self): diff --git a/src/robot_interface/models/geometry/frame.py b/src/robot_interface/models/geometry/frame.py index 06d0cb21..8abb1caf 100644 --- a/src/robot_interface/models/geometry/frame.py +++ b/src/robot_interface/models/geometry/frame.py @@ -3,7 +3,8 @@ class Frame(str, Enum): """ - Robot frame implies the local frame on the operating robot. This will depend on the robots internal mapping. + Robot frame implies the local frame on the operating robot. This will depend on the + robots internal mapping. Asset frame is the frame of the asset which the robot operates in. """ diff --git a/src/robot_interface/models/geometry/orientation.py b/src/robot_interface/models/geometry/orientation.py index fc618359..6dca5eb1 100644 --- a/src/robot_interface/models/geometry/orientation.py +++ b/src/robot_interface/models/geometry/orientation.py @@ -11,9 +11,10 @@ @dataclass class Orientation: """ - This class represents an orientation using quaternions. The quaternion is used throughout the project. - Methods that utilize Euler angles will all follow the yaw, pitch, roll convention which rotates around the ZYX axis - with intrinsic rotations. + This class represents an orientation using quaternions. The quaternion is used + throughout the project. + Methods that utilize Euler angles will all follow the yaw, pitch, roll convention + which rotates around the ZYX axis with intrinsic rotations. """ x: float @@ -42,8 +43,8 @@ def as_euler( wrap_angles: bool = False, ) -> list: """ - Retrieve the orientation as yaw, pitch, roll Euler coordinates. This function uses the ZYX intrinsic rotations - as standard convention. + Retrieve the orientation as yaw, pitch, roll Euler coordinates. This function + uses the ZYX intrinsic rotations as standard convention. :param degrees: Set to true to retrieve angles as degrees. :return: List of euler angles [yaw, pitch, roll] """ diff --git a/src/robot_interface/models/mission/task.py b/src/robot_interface/models/mission/task.py index eddb625b..2c322828 100644 --- a/src/robot_interface/models/mission/task.py +++ b/src/robot_interface/models/mission/task.py @@ -63,7 +63,7 @@ class InspectionTask(Task): @dataclass class MotionTask(Task): """ - Base class for all tasks which should cause the robot to move, but not return a result. + Base class for all tasks which should move the robot, but not return a result. """ pass diff --git a/tests/integration/turtlebot/test_successful_mission.py b/tests/integration/turtlebot/test_successful_mission.py index 4e68bfe0..2dc03034 100644 --- a/tests/integration/turtlebot/test_successful_mission.py +++ b/tests/integration/turtlebot/test_successful_mission.py @@ -94,7 +94,7 @@ def test_successful_mission( _id: int = 2 - response = client.post( + _ = client.post( f"schedule/start-mission?ID={_id}", headers={"Authorization": "Bearer {}".format(access_token)}, ) diff --git a/tests/isar/apis/scheduler/test_scheduler_routes.py b/tests/isar/apis/scheduler/test_scheduler_routes.py index 61dafc81..caa44e1c 100644 --- a/tests/isar/apis/scheduler/test_scheduler_routes.py +++ b/tests/isar/apis/scheduler/test_scheduler_routes.py @@ -5,7 +5,6 @@ import pytest from isar.apis.security.authentication import Authenticator -from isar.config.settings import robot_settings from isar.mission_planner.local_planner import LocalPlanner from isar.mission_planner.mission_planner_interface import MissionPlannerError from isar.models.communication.messages import ( diff --git a/tests/isar/models/communication/test_queues.py b/tests/isar/models/communication/test_queues.py index bbd4632a..79979fdc 100644 --- a/tests/isar/models/communication/test_queues.py +++ b/tests/isar/models/communication/test_queues.py @@ -7,18 +7,18 @@ def test_queues(self): assert queues.start_mission is not None assert ( queues.start_mission.input is not None - and queues.start_mission.input.maxsize is 1 + and queues.start_mission.input.maxsize == 1 ) assert ( queues.start_mission.output is not None - and queues.start_mission.output.maxsize is 1 + and queues.start_mission.output.maxsize == 1 ) assert queues.stop_mission is not None assert ( queues.stop_mission.input is not None - and queues.stop_mission.input.maxsize is 1 + and queues.stop_mission.input.maxsize == 1 ) assert ( queues.stop_mission.output is not None - and queues.stop_mission.output.maxsize is 1 + and queues.stop_mission.output.maxsize == 1 ) diff --git a/tests/isar/services/readers/test_base_reader.py b/tests/isar/services/readers/test_base_reader.py index 716a7213..d04723a5 100644 --- a/tests/isar/services/readers/test_base_reader.py +++ b/tests/isar/services/readers/test_base_reader.py @@ -1,5 +1,4 @@ from dataclasses import asdict -from pathlib import Path from typing import Any import pytest