Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: Add a parameter metadata download fallback URL #37

Merged
merged 1 commit into from
Aug 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions MethodicConfigurator/annotate_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ def format_params(param_dict: Dict[str, 'Par'], file_format: str = "missionplann
Parameters:
param_dict (Dict[str, 'Par']): A dictionary of 'Par' objects.
Each key is a parameter name and each value is a 'Par' object.
Par can be a simple float or a Par object with a comment.
file_format (str): Can be "missionplanner" or "mavproxy"

Returns:
Expand Down Expand Up @@ -303,14 +304,15 @@ def print_out(formatted_params: List[str], name: str) -> None:
print(line)


def get_xml_data(base_url: str, directory: str, filename: str) -> ET.Element:
def get_xml_data(base_url: str, directory: str, filename: str, vehicle_type: str) -> ET.Element:
"""
Fetches XML data from a local file or a URL.

Args:
base_url (str): The base URL for fetching the XML file.
directory (str): The directory where the XML file is expected.
filename (str): The name of the XML file.
vehicle_type (str): The type of the vehicle.

Returns:
ET.Element: The root element of the parsed XML data.
Expand All @@ -336,13 +338,24 @@ def get_xml_data(base_url: str, directory: str, filename: str) -> ET.Element:
raise SystemExit("requests package is not installed") from exc
try:
# Send a GET request to the URL
response = requests_get(base_url + filename, timeout=5)
url = base_url + filename
response = requests_get(url, timeout=5)
if response.status_code != 200:
logging.critical("Remote URL: %s", base_url + filename)
logging.warning("Remote URL: %s", url)
raise requests_exceptions.RequestException(f"HTTP status code {response.status_code}")
except requests_exceptions.RequestException as e:
logging.critical("Unable to fetch XML data: %s", e)
raise SystemExit("unable to fetch online XML documentation") from e
logging.warning("Unable to fetch XML data: %s", e)
# Send a GET request to the URL to the fallback (DEV) URL
try:
url = BASE_URL + vehicle_type + '/' + PARAM_DEFINITION_XML_FILE
logging.warning("Falling back to the DEV XML file: %s", url)
response = requests_get(url, timeout=5)
if response.status_code != 200:
logging.critical("Remote URL: %s", url)
raise requests_exceptions.RequestException(f"HTTP status code {response.status_code}")
except requests_exceptions.RequestException as exp:
logging.critical("Unable to fetch XML data: %s", exp)
raise SystemExit("unable to fetch online XML documentation") from exp
# Get the text content of the response
xml_data = response.text
try:
Expand Down Expand Up @@ -695,7 +708,7 @@ def get_xml_url(vehicle_type: str, firmware_version: str) -> str:

def parse_parameter_metadata(xml_url: str, xml_dir: str, xml_file: str,
vehicle_type: str, max_line_length: int) -> Dict[str, Any]:
xml_root = get_xml_data(xml_url, xml_dir, xml_file)
xml_root = get_xml_data(xml_url, xml_dir, xml_file, vehicle_type)
return create_doc_dict(xml_root, vehicle_type, max_line_length)


Expand Down
6 changes: 3 additions & 3 deletions MethodicConfigurator/backend_flightcontroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,9 @@ def __process_autopilot_version(self, m, banner_msgs) -> str:
# the banner message after the ChibiOS one contains the FC type
fc_product = ''
if os_custom_version_index is not None:
fc_type_msgs = banner_msgs[os_custom_version_index+1].split(' ')
if len(fc_type_msgs) >= 3:
fc_product = fc_type_msgs[0]
fc_product_banner_substrings = banner_msgs[os_custom_version_index+1].split(' ')
if len(fc_product_banner_substrings) >= 3:
fc_product = fc_product_banner_substrings[0]
if fc_product != self.info.product:
logging_warning("FC product mismatch: %s (BANNER)!= %s(AUTOPILOT_VERSION)", fc_product, self.info.product)
self.info.product = fc_product # force the one from the banner because it is more reliable
Expand Down
18 changes: 9 additions & 9 deletions unittests/annotate_params_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def test_get_xml_data_local_file(self, mock_load_param, mock_isfile, mock_open):
mock_load_param.side_effect = FileNotFoundError

# Call the function with a local file
result = get_xml_data("/path/to/local/file/", ".", "test.xml")
result = get_xml_data("/path/to/local/file/", ".", "test.xml", "ArduCopter")

# Check the result
self.assertIsInstance(result, ET.Element)
Expand All @@ -97,7 +97,7 @@ def test_get_xml_data_remote_file(self, mock_get):
pass

# Call the function with a remote file
result = get_xml_data("http://example.com/", ".", "test.xml")
result = get_xml_data("http://example.com/", ".", "test.xml", "ArduCopter")

# Check the result
self.assertIsInstance(result, ET.Element)
Expand All @@ -120,7 +120,7 @@ def side_effect(filename):
mock_open = mock.mock_open(read_data='<root></root>')
with patch('builtins.open', mock_open):
# Call the function with a filename that exists in the script directory
result = get_xml_data(BASE_URL, ".", PARAM_DEFINITION_XML_FILE)
result = get_xml_data(BASE_URL, ".", PARAM_DEFINITION_XML_FILE, "ArduCopter")

# Check the result
self.assertIsInstance(result, ET.Element)
Expand All @@ -140,7 +140,7 @@ def test_get_xml_data_no_requests_package(self):

# Call the function with a remote file
with self.assertRaises(SystemExit):
get_xml_data("http://example.com/", ".", "test.xml")
get_xml_data("http://example.com/", ".", "test.xml", "ArduCopter")

@patch('requests.get')
def test_get_xml_data_request_failure(self, mock_get):
Expand All @@ -155,7 +155,7 @@ def test_get_xml_data_request_failure(self, mock_get):

# Call the function with a remote file
with self.assertRaises(SystemExit):
get_xml_data("http://example.com/", ".", "test.xml")
get_xml_data("http://example.com/", ".", "test.xml", "ArduCopter")

@patch('requests.get')
def test_get_xml_data_valid_xml(self, mock_get):
Expand All @@ -164,7 +164,7 @@ def test_get_xml_data_valid_xml(self, mock_get):
mock_get.return_value.text = "<root></root>"

# Call the function with a remote file
result = get_xml_data("http://example.com/", ".", "test.xml")
result = get_xml_data("http://example.com/", ".", "test.xml", "ArduCopter")

# Check the result
self.assertIsInstance(result, ET.Element)
Expand All @@ -183,7 +183,7 @@ def test_get_xml_data_invalid_xml(self, mock_get):

# Call the function with a remote file
with self.assertRaises(ET.ParseError):
get_xml_data("http://example.com/", ".", "test.xml")
get_xml_data("http://example.com/", ".", "test.xml", "ArduCopter")

@patch('requests.get')
@patch('os.path.isfile')
Expand All @@ -201,7 +201,7 @@ def test_get_xml_data_missing_file(self, mock_isfile, mock_get):

# Call the function with a local file
with self.assertRaises(FileNotFoundError):
get_xml_data("/path/to/local/file/", ".", "test.xml")
get_xml_data("/path/to/local/file/", ".", "test.xml", "ArduCopter")

@patch('requests.get')
def test_get_xml_data_network_issue(self, mock_get):
Expand All @@ -210,7 +210,7 @@ def test_get_xml_data_network_issue(self, mock_get):

# Call the function with a remote file
with self.assertRaises(SystemExit):
get_xml_data("http://example.com/", ".", "test.xml")
get_xml_data("http://example.com/", ".", "test.xml", "ArduCopter")

def test_remove_prefix(self):
# Test case 1: Normal operation
Expand Down