diff --git a/.azure/azure-ci-build-pipeline.yaml b/.azure/azure-ci-build-pipeline.yaml index 1a7b4870..f0a1793e 100644 --- a/.azure/azure-ci-build-pipeline.yaml +++ b/.azure/azure-ci-build-pipeline.yaml @@ -14,48 +14,33 @@ parameters: - name: matrix type: object default: - # - job_name: 'UbuntuPython38' - # py: '3.8' - # img: 'ubuntu-latest' - # every_time: false - # publish_coverage: false - # - job_name: 'UbuntuPython310' - # py: '3.10' - # img: 'ubuntu-latest' - # every_time: true - # publish_coverage: true - - job_name: 'UbuntuPython312_TEST' - py: '3.12' + - job_name: 'UbuntuPython38' + py: '3.8' + img: 'ubuntu-latest' + every_time: false + publish_coverage: false + - job_name: 'UbuntuPython311' + py: '3.11' img: 'ubuntu-latest' every_time: true publish_coverage: true - # - job_name: 'WindowsPython38' - # py: '3.8' - # img: 'windows-latest' - # every_time: false - # publish_coverage: false - # - job_name: 'WindowsPython310' - # py: '3.10' - # img: 'windows-latest' - # every_time: false - # publish_coverage: false - - job_name: 'WindowsPython312_TEST' - py: '3.12' + - job_name: 'WindowsPython38' + py: '3.8' img: 'windows-latest' every_time: false publish_coverage: false - # - job_name: 'MacOSPython38' - # py: '3.8' - # img: 'macOS-latest' - # every_time: false - # publish_coverage: false - # - job_name: 'MacOSPython310' - # py: '3.10' - # img: 'macOS-latest' - # every_time: false - # publish_coverage: false - - job_name: 'MacOSPython312_TEST' - py: '3.12' + - job_name: 'WindowsPython311' + py: '3.11' + img: 'windows-latest' + every_time: false + publish_coverage: false + - job_name: 'MacOSPython38' + py: '3.8' + img: 'macOS-latest' + every_time: false + publish_coverage: false + - job_name: 'MacOSPython311' + py: '3.11' img: 'macOS-latest' every_time: false publish_coverage: false diff --git a/README.md b/README.md index 927aa17c..c57d9c6b 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ primaite setup #### Unix **Prerequisites:** -* Manual install of Python >= 3.8 < 3.11 +* Manual install of Python >= 3.8 < 3.12 ``` bash sudo add-apt-repository ppa:deadsnakes/ppa diff --git a/docs/conf.py b/docs/conf.py index 93e8a447..a666e460 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -30,7 +30,8 @@ release = version # set global variables rst_prolog = f""" -.. |VERSION| replace:: {release} """ # noqa +.. |VERSION| replace:: {release} +""" html_title = f"{project} v{release} docs" diff --git a/pyproject.toml b/pyproject.toml index c71b55a6..2619da90 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "primaite" description = "PrimAITE (Primary-level AI Training Environment) is a simulation environment for training AI under the ARCD programme." authors = [{name="Defence Science and Technology Laboratory UK", email="oss@dstl.gov.uk"}] license = {file = "LICENSE"} -requires-python = ">=3.8, <3.13" +requires-python = ">=3.8, <3.12" dynamic = ["version", "readme"] classifiers = [ "License :: OSI Approved :: MIT License", @@ -20,6 +20,7 @@ classifiers = [ "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3 :: Only", ] diff --git a/src/primaite/game/agent/rewards.py b/src/primaite/game/agent/rewards.py index 36a984dd..0222bfcc 100644 --- a/src/primaite/game/agent/rewards.py +++ b/src/primaite/game/agent/rewards.py @@ -231,7 +231,7 @@ class WebpageUnavailablePenalty(AbstractReward): # If the last request did actually go through, then check if the webpage also loaded web_browser_state = access_from_nested_dict(state, self.location_in_state) - if web_browser_state is NOT_PRESENT_IN_STATE or "history" not in web_browser_state: # noqa + if web_browser_state is NOT_PRESENT_IN_STATE or "history" not in web_browser_state: _LOGGER.debug( "Web browser reward could not be calculated because the web browser history on node", f"{self._node} was not reported in the simulation state. Returning 0.0", diff --git a/src/primaite/simulator/network/container.py b/src/primaite/simulator/network/container.py index 717d04b3..17308c97 100644 --- a/src/primaite/simulator/network/container.py +++ b/src/primaite/simulator/network/container.py @@ -248,7 +248,7 @@ class Network(SimComponent): hostname_b = node_b.hostname if node_b else None port_a = link.endpoint_a.port_num port_b = link.endpoint_b.port_num - link_key = f"{hostname_a}: eth-{port_a}<->{hostname_b}: eth-{port_b}" + link_key = f"{hostname_a}:eth-{port_a}<->{hostname_b}:eth-{port_b}" state["links"][link_key] = link.describe_state() state["links"][link_key]["hostname_a"] = hostname_a state["links"][link_key]["hostname_b"] = hostname_b diff --git a/src/primaite/simulator/network/hardware/base.py b/src/primaite/simulator/network/hardware/base.py index 1d305598..78a0bf2d 100644 --- a/src/primaite/simulator/network/hardware/base.py +++ b/src/primaite/simulator/network/hardware/base.py @@ -56,7 +56,7 @@ def generate_mac_address(oui: Optional[str] = None) -> str: if oui: oui_pattern = re.compile(r"^([0-9A-Fa-f]{2}[:-]){2}[0-9A-Fa-f]{2}$") if not oui_pattern.match(oui): - msg = f"Invalid oui. The oui should be in the format xx:xx:xx, where x is a hexadecimal digit, got '{oui}'" # noqa + msg = f"Invalid oui. The oui should be in the format xx:xx:xx, where x is a hexadecimal digit, got '{oui}'" _LOGGER.error(msg) raise ValueError(msg) oui_bytes = [int(chunk, 16) for chunk in oui.split(":")] @@ -64,7 +64,7 @@ def generate_mac_address(oui: Optional[str] = None) -> str: else: mac = random_bytes - return ":".join(f"{b:02x}" for b in mac) # noqa + return ":".join(f"{b:02x}" for b in mac) class NetworkInterface(SimComponent, ABC): @@ -599,7 +599,7 @@ class Link(SimComponent): @property def current_load_percent(self) -> str: """Get the current load formatted as a percentage string.""" - return f"{self.current_load / self.bandwidth:.5f}%" # noqa + return f"{self.current_load / self.bandwidth:.5f}%" def endpoint_up(self): """Let the Link know and endpoint has been brought up.""" @@ -652,7 +652,7 @@ class Link(SimComponent): # Load the frame size on the link self.current_load += frame_size _LOGGER.debug( - f"Added {frame_size:.3f} Mbits to {self}, current load {self.current_load:.3f} Mbits " # noqa + f"Added {frame_size:.3f} Mbits to {self}, current load {self.current_load:.3f} Mbits " f"({self.current_load_percent})" ) return True diff --git a/src/primaite/simulator/network/protocols/icmp.py b/src/primaite/simulator/network/protocols/icmp.py index b891fe5a..35b0a05d 100644 --- a/src/primaite/simulator/network/protocols/icmp.py +++ b/src/primaite/simulator/network/protocols/icmp.py @@ -100,7 +100,7 @@ class ICMPPacket(BaseModel): icmp_type = info.data["icmp_type"] if get_icmp_type_code_description(icmp_type, v): return v - msg = f"No Matching ICMP code for type: {icmp_type.name}, code: {v}" + msg = f"No Matching ICMP code for type:{icmp_type.name}, code:{v}" _LOGGER.error(msg) raise ValueError(msg) @@ -109,6 +109,6 @@ class ICMPPacket(BaseModel): description = get_icmp_type_code_description(self.icmp_type, self.icmp_code) if description: return description - msg = f"No Matching ICMP code for type: {self.icmp_type.name}, code: {self.icmp_code}" + msg = f"No Matching ICMP code for type:{self.icmp_type.name}, code:{self.icmp_code}" _LOGGER.error(msg) raise ValueError(msg) diff --git a/src/primaite/simulator/system/services/dns/dns_client.py b/src/primaite/simulator/system/services/dns/dns_client.py index 1baef868..063ff74f 100644 --- a/src/primaite/simulator/system/services/dns/dns_client.py +++ b/src/primaite/simulator/system/services/dns/dns_client.py @@ -81,7 +81,7 @@ class DNSClient(Service): # check if the domain is already in the DNS cache if target_domain in self.dns_cache: self.sys_log.info( - f"{self.name}: Domain lookup for {target_domain} successful, " + f"{self.name}: Domain lookup for {target_domain} successful," f"resolves to {self.dns_cache[target_domain]}" ) return True diff --git a/src/primaite/simulator/system/services/ftp/ftp_service.py b/src/primaite/simulator/system/services/ftp/ftp_service.py index 75c8daab..70ba74d7 100644 --- a/src/primaite/simulator/system/services/ftp/ftp_service.py +++ b/src/primaite/simulator/system/services/ftp/ftp_service.py @@ -147,7 +147,7 @@ class FTPServiceABC(Service, ABC): retrieved_file: File = self.file_system.get_file(folder_name=folder_name, file_name=file_name) # if file does not exist, return an error - if not retrieved_file: # noqa + if not retrieved_file: self.sys_log.error( f"File {payload.ftp_command_args['dest_folder_name']}/" f"{payload.ftp_command_args['dest_file_name']} does not exist in {self.sys_log.hostname}" diff --git a/src/primaite/simulator/system/services/icmp/icmp.py b/src/primaite/simulator/system/services/icmp/icmp.py index 14aa47e4..c4b4173f 100644 --- a/src/primaite/simulator/system/services/icmp/icmp.py +++ b/src/primaite/simulator/system/services/icmp/icmp.py @@ -60,7 +60,7 @@ class ICMP(Service): if target_ip_address.is_loopback: self.sys_log.info("Pinging loopback address") return any(network_interface.enabled for network_interface in self.network_interfaces.values()) - self.sys_log.info(f"Pinging {target_ip_address}: ", to_terminal=True) + self.sys_log.info(f"Pinging {target_ip_address}:", to_terminal=True) sequence, identifier = 0, None while sequence < pings: sequence, identifier = self._send_icmp_echo_request(target_ip_address, sequence, identifier, pings)