diff --git a/CHANGELOG.md b/CHANGELOG.md index de86885..6dcb8ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +* Fix Python exception if the "init" or "update" commands were not executed + ## 1.1.1 - 2022-05-19 * Fix the search when there is a space in the plugin name diff --git a/qgis_plugin_manager/remote.py b/qgis_plugin_manager/remote.py index 89253cd..8a4bf94 100644 --- a/qgis_plugin_manager/remote.py +++ b/qgis_plugin_manager/remote.py @@ -26,6 +26,32 @@ def __init__(self, folder: Path): self.list = None self.list_plugins = None + def remote_is_ready(self) -> bool: + """ Return if the remote is ready to be parsed. """ + source_list = Path(self.folder / 'sources.list') + if not source_list.exists(): + print(f"{Level.Critical}The sources.list file does not exist{Level.End}") + print("Use the 'init' command to create the file") + return False + + if self.list is None: + self.remote_list() + + cache = Path(self.folder / ".cache_qgis_plugin_manager") + for server in self.list: + filename = self.server_cache_filename(cache, server) + + if not filename.exists(): + print( + f"{Level.Critical}" + f"The 'update' command has not been done before. " + f"The repository {server} has not been fetched before." + f"{Level.End}" + ) + return False + + return True + def remote_list(self) -> list: """Return the list of remotes configured. @@ -53,14 +79,15 @@ def remote_list(self) -> list: f"{Level.End}" ) print( - f"Instead of\n{raw_line}" - f"\n" - f"you should have" - f"\n" - f"https://plugins.qgis.org/plugins/plugins.xml?qgis=[VERSION]" + f"Instead of\n'{raw_line}'" + f"\nin your 'sources.list' file, you should have" f"\n" + f"'https://plugins.qgis.org/plugins/plugins.xml?qgis=[VERSION]'" + f"\n\n" f"Can you remove the file sources.list ? 'qgis-plugin-manager init' will " - f"regenerate it using dynamic QGIS version if QGIS is well configured." + f"regenerate it using dynamic QGIS version if QGIS is well configured.\n" + f"This just warning, the process will continue with the hardcoded QGIS version." + f"\n\n" ) raw_line = raw_line.replace("[VERSION]", f"{qgis_version[0]}.{qgis_version[1]}") @@ -103,22 +130,19 @@ def update(self): print(f"\t{e}") continue - filename = "" - for x in server: - if x.isalnum(): - filename += x - else: - filename += '-' + filename = self.server_cache_filename(cache, server) - filename = re.sub(r"\-+", "-", filename) # Binary mode does not support encoding parameter - with open(Path(cache / f"{filename}.xml"), 'wb') as output: + with open(filename, 'wb') as output: output.write(f.read()) print(f"\t{Level.Success}Ok{Level.End}") def xml_in_folder(self) -> List[Path]: """ Returns the list of XML files in the folder. """ + if not self.remote_is_ready(): + return [] + cache = Path(self.folder / ".cache_qgis_plugin_manager") if not cache.exists(): cache.mkdir() @@ -133,9 +157,6 @@ def xml_in_folder(self) -> List[Path]: xml.append(xml_file) - if len(xml) < 1: - print(f"{Level.Warning}No remote repositories found !{Level.End}") - return xml def available_plugins(self) -> Dict: @@ -222,8 +243,12 @@ def similar_names(self, plugin_name_wanted: str) -> List[str]: return similar - def search(self, search_string: str) -> List: + def search(self, search_string: str, strict=True) -> List: """ Search in plugin names and tags.""" + # strict is used in tests to not check if the remote is ready + if strict and not self.remote_is_ready(): + return [] + if self.list is None: self.remote_list() @@ -245,6 +270,9 @@ def install(self, plugin_name, version="latest") -> bool: Default version is latest. """ + if not self.remote_is_ready(): + return False + xml_version = self.latest(plugin_name) if xml_version is None: print(f"{Level.Warning}Plugin {plugin_name} {version} not found.{Level.End}") @@ -313,3 +341,16 @@ def install(self, plugin_name, version="latest") -> bool: print(f"Installed with user '{current_user}'") print("Please check file permissions and owner according to the user running QGIS Server.") return True + + @staticmethod + def server_cache_filename(cache_folder, server) -> Path: + """ Return the path for XML file. """ + filename = "" + for x in server: + if x.isalnum(): + filename += x + else: + filename += '-' + + filename = re.sub(r"\-+", "-", filename) + return Path(cache_folder / f"{filename}.xml") diff --git a/test/test_remote.py b/test/test_remote.py index b735537..64991e9 100644 --- a/test/test_remote.py +++ b/test/test_remote.py @@ -46,8 +46,8 @@ def test_plugin_name_with_space_and_tags(self): # Test the search self.assertListEqual([], self.remote.search("foo")) - self.assertListEqual(['Data Plotly'], self.remote.search("dataviz")) - self.assertListEqual(['Data Plotly'], self.remote.search("dataplotly")) + self.assertListEqual(['Data Plotly'], self.remote.search("dataviz", strict=False)) + self.assertListEqual(['Data Plotly'], self.remote.search("dataplotly", strict=False)) def test_search_with_space_in_name(self): """ Test Lizmap should give 2 values : Lizmap and 'Lizmap server'. """ @@ -72,7 +72,7 @@ def test_search_with_space_in_name(self): ) # Test the search - self.assertListEqual(['Lizmap', 'Lizmap server'], self.remote.search("lizmap")) + self.assertListEqual(['Lizmap', 'Lizmap server'], self.remote.search("lizmap", strict=False)) @unittest.expectedFailure def test_latest_pgmetadata(self):