def retrieve_macros_from_git(self): """Retrieve macros from FreeCAD-macros.git Emits a signal for each macro in https://github.com/FreeCAD/FreeCAD-macros.git """ if not have_git: self.info_label_signal.emit("GitPython not installed! Cannot retrieve macros from Git") FreeCAD.Console.PrintWarning(translate("AddonsInstaller", "GitPython not installed! Cannot retrieve macros from git")+"\n") return self.info_label_signal.emit("Downloading list of macros from git...") try: git.Repo.clone_from("https://github.com/FreeCAD/FreeCAD-macros.git", self.repo_dir) except Exception: FreeCAD.Console.PrintWarning(translate("AddonsInstaller", "Something went wrong with the Git Macro Retrieval, " "possibly the Git executable is not in the path") + "\n") for dirpath, _, filenames in os.walk(self.repo_dir): if ".git" in dirpath: continue for filename in filenames: if filename.lower().endswith(".fcmacro"): macro = Macro(filename[:-8]) # Remove ".FCMacro". macro.on_git = True macro.src_filename = os.path.join(dirpath, filename) self.macros.append(macro)
def retrieve_macros_from_git(self): """Retrieve macros from FreeCAD-macros.git Emits a signal for each macro in https://github.com/FreeCAD/FreeCAD-macros.git """ try: import git except ImportError: self.info_label_signal.emit( "GitPython not installed! Cannot retrieve macros from Git") FreeCAD.Console.PrintWarning( translate( 'AddonsInstaller', 'GitPython not installed! Cannot retrieve macros from git') + "\n") return self.info_label_signal.emit('Downloading list of macros from git...') git.Repo.clone_from('https://github.com/FreeCAD/FreeCAD-macros.git', self.repo_dir) for dirpath, _, filenames in os.walk(self.repo_dir): if '.git' in dirpath: continue for filename in filenames: if filename.lower().endswith('.fcmacro'): macro = Macro(filename[:-8]) # Remove ".FCMacro". macro.on_git = True macro.src_filename = os.path.join(dirpath, filename) self.macros.append(macro)
def retrieve_macros_from_wiki(self): """Retrieve macros from the wiki Read the wiki and emit a signal for each found macro. Reads only the page https://www.freecadweb.org/wiki/Macros_recipes """ self.info_label_signal.emit( "Downloading list of macros from the FreeCAD wiki...") self.progressbar_show.emit(True) u = utils.urlopen("https://www.freecadweb.org/wiki/Macros_recipes") if not u: FreeCAD.Console.PrintWarning( translate( "AddonsInstaller", "Appears to be an issue connecting to the Wiki, " "therefore cannot retrieve Wiki macro list at this time") + "\n") return p = u.read() u.close() if sys.version_info.major >= 3 and isinstance(p, bytes): p = p.decode("utf-8") macros = re.findall('title="(Macro.*?)"', p) macros = [mac for mac in macros if ("translated" not in mac)] for mac in macros: macname = mac[6:] # Remove "Macro ". macname = macname.replace("&", "&") if (macname not in macros_blacklist) and ("recipes" not in macname.lower()): macro = Macro(macname) macro.on_wiki = True self.macros.append(macro)
def retrieve_macros_from_wiki(self): """Retrieve macros from the wiki Read the wiki and emit a signal for each found macro. Reads only the page https://www.freecadweb.org/wiki/Macros_recipes. """ self.info_label_signal.emit( "Downloading list of macros from the FreeCAD wiki...") self.progressbar_show.emit(True) u = utils.urlopen("https://www.freecadweb.org/wiki/Macros_recipes") if not u: return p = u.read() u.close() if sys.version_info.major >= 3 and isinstance(p, bytes): p = p.decode("utf-8") macros = re.findall('title="(Macro.*?)"', p) macros = [mac for mac in macros if ('translated' not in mac)] for mac in macros: macname = mac[6:] # Remove "Macro ". macname = macname.replace("&", "&") if (macname not in MACROS_BLACKLIST) and ('recipes' not in macname.lower()): macro = Macro(macname) macro.on_wiki = True self.macros.append(macro)
def _retrieve_macros_from_wiki(self): """Retrieve macros from the wiki Read the wiki and emit a signal for each found macro. Reads only the page https://wiki.freecad.org/Macros_recipes """ p = NetworkManager.AM_NETWORK_MANAGER.blocking_get( "https://wiki.freecad.org/Macros_recipes" ) if not p: # The Qt Python translation extractor doesn't support splitting this string (yet) # pylint: disable=line-too-long FreeCAD.Console.PrintWarning( translate( "AddonsInstaller", "Error connecting to the Wiki, FreeCAD cannot retrieve the Wiki macro list at this time", ) + "\n" ) return p = p.data().decode("utf8") macros = re.findall('title="(Macro.*?)"', p) macros = [mac for mac in macros if "translated" not in mac] macro_names = [] for _, mac in enumerate(macros): if self.current_thread.isInterruptionRequested(): return macname = mac[6:] # Remove "Macro ". macname = macname.replace("&", "&") if not macname: continue if ( (macname not in self.macros_reject_list) and ("recipes" not in macname.lower()) and (macname not in macro_names) ): macro_names.append(macname) macro = Macro(macname) if macro.name in self.package_names: FreeCAD.Console.PrintLog( f"Ignoring second macro named {macro.name} (found on wiki)\n" ) continue # We already have a macro with this name self.package_names.append(macro.name) macro.on_wiki = True macro.parsed = False repo = Addon.from_macro(macro) repo.url = "https://wiki.freecad.org/Macros_recipes" utils.update_macro_installation_details(repo) self.addon_repo.emit(repo)
def test_version_from_int(self): outfile = self.generate_macro_file() with open(outfile) as f: lines = f.readlines() output_lines = [] for line in lines: if "VERSION" in line: line = "__Version__ = 1" output_lines.append(line) with open(outfile, "w") as f: f.write("\n".join(output_lines)) m = Macro("Unit Test Macro") m.fill_details_from_file(outfile) self.assertEqual(m.version, "1")
def test_version_from_date(self): replacements = { "DATE": "2022-03-09", } outfile = self.generate_macro_file(replacements) with open(outfile) as f: lines = f.readlines() output_lines = [] for line in lines: if "VERSION" in line: line = "__Version__ = __Date__" output_lines.append(line) with open(outfile, "w") as f: f.write("\n".join(output_lines)) m = Macro("Unit Test Macro") m.fill_details_from_file(outfile) self.assertEqual(m.version, "2022-03-09")
def test_create_from_macro(self): macro_file = os.path.join(self.test_dir, "DoNothing.FCMacro") macro = Macro("DoNothing") macro.fill_details_from_file(macro_file) addon = Addon.from_macro(macro) self.assertEqual(addon.repo_type, Addon.Kind.MACRO) self.assertEqual(addon.name, "DoNothing") self.assertEqual( addon.macro.comment, "Do absolutely nothing. For Addon Manager unit tests.") self.assertEqual(addon.url, "https://github.com/FreeCAD/FreeCAD") self.assertEqual(addon.macro.version, "1.0") self.assertEqual(len(addon.macro.other_files), 3) self.assertEqual(addon.macro.author, "Chris Hennes") self.assertEqual(addon.macro.date, "2022-02-28") self.assertEqual(addon.macro.icon, "not_real.png") self.assertEqual(addon.macro.xpm, "")
def from_macro(self, macro: Macro): if macro.is_installed(): status = AddonManagerRepo.UpdateStatus.UNCHECKED else: status = AddonManagerRepo.UpdateStatus.NOT_INSTALLED instance = AddonManagerRepo(macro.name, macro.url, status, "master") instance.macro = macro instance.repo_type = AddonManagerRepo.RepoType.MACRO instance.description = macro.desc return instance
def from_macro(cls, macro: Macro): """Create an Addon object from a Macro wrapper object""" if macro.is_installed(): status = Addon.Status.UNCHECKED else: status = Addon.Status.NOT_INSTALLED instance = Addon(macro.name, macro.url, status, "master") instance.macro = macro instance.repo_type = Addon.Kind.MACRO instance.description = macro.desc return instance
def retrieve_macros_from_wiki(self): """Retrieve macros from the wiki Read the wiki and emit a signal for each found macro. Reads only the page https://www.freecadweb.org/wiki/Macros_recipes. """ self.info_label_signal.emit("Downloading list of macros...") self.progressbar_show.emit(True) u = urlopen("https://www.freecadweb.org/wiki/Macros_recipes") p = u.read() u.close() if sys.version_info.major >= 3 and isinstance(p, bytes): p = p.decode("utf-8") macros = re.findall('title="(Macro.*?)"', p) macros = [mac for mac in macros if ('translated' not in mac)] for mac in macros: macname = mac[6:] # Remove "Macro ". macname = macname.replace("&","&") if (macname not in MACROS_BLACKLIST) and ('recipes' not in macname.lower()): macro = Macro(macname) macro.on_wiki = True self.macros.append(macro)
def run(self): """Rarely called directly: create an instance and call start() on it instead to launch in a new thread""" with open(self.cache_file, "r", encoding="utf-8") as f: data = f.read() dict_data = json.loads(data) for item in dict_data: if QtCore.QThread.currentThread().isInterruptionRequested(): return new_macro = Macro.from_cache(item) repo = Addon.from_macro(new_macro) utils.update_macro_installation_details(repo) self.add_macro_signal.emit(repo)
def test_xpm(self): outfile = self.generate_macro_file() xpm_data = """/* XPM */ static char * blarg_xpm[] = { "16 7 2 1", "* c #000000", ". c #ffffff", "**..*...........", "*.*.*...........", "**..*..**.**..**", "*.*.*.*.*.*..*.*", "**..*..**.*...**", "...............*", ".............**." };""" with open(outfile) as f: contents = f.read() contents += f"\n__xpm__ = \"\"\"{xpm_data}\"\"\"\n" with open(outfile, "w") as f: f.write(contents) m = Macro("Unit Test Macro") m.fill_details_from_file(outfile) self.assertEqual(m.xpm, xpm_data)
def retrieve_macros_from_git(self): """Retrieve macros from FreeCAD-macros.git Emits a signal for each macro in https://github.com/FreeCAD/FreeCAD-macros.git. """ try: import git except ImportError: self.info_label_signal.emit("GitPython not installed! Cannot retrieve macros from git") FreeCAD.Console.PrintWarning('GitPython not installed! Cannot retrieve macros from git') return self.info_label_signal.emit('Downloading list of macros for git...') git.Repo.clone_from('https://github.com/FreeCAD/FreeCAD-macros.git', self.repo_dir) for dirpath, _, filenames in os.walk(self.repo_dir): if '.git' in dirpath: continue for filename in filenames: if filename.lower().endswith('.fcmacro'): macro = Macro(filename[:-8]) # Remove ".FCMacro". macro.on_git = True macro.src_filename = os.path.join(dirpath, filename) self.macros.append(macro)
def _retrieve_macros_from_git(self): """Retrieve macros from FreeCAD-macros.git Emits a signal for each macro in https://github.com/FreeCAD/FreeCAD-macros.git """ macro_cache_location = utils.get_cache_file_name("Macros") if not self.git_manager: message = translate( "AddonsInstaller", "Git is disabled, skipping git macros", ) self.status_message.emit(message) FreeCAD.Console.PrintWarning(message + "\n") return update_succeeded = self._update_local_git_repo() if not update_succeeded: return n_files = 0 for _, _, filenames in os.walk(macro_cache_location): n_files += len(filenames) counter = 0 for dirpath, _, filenames in os.walk(macro_cache_location): counter += 1 if self.current_thread.isInterruptionRequested(): return if ".git" in dirpath: continue for filename in filenames: if self.current_thread.isInterruptionRequested(): return if filename.lower().endswith(".fcmacro"): macro = Macro(filename[:-8]) # Remove ".FCMacro". if macro.name in self.package_names: FreeCAD.Console.PrintLog( f"Ignoring second macro named {macro.name} (found on git)\n" ) continue # We already have a macro with this name self.package_names.append(macro.name) macro.on_git = True macro.src_filename = os.path.join(dirpath, filename) macro.fill_details_from_file(macro.src_filename) repo = Addon.from_macro(macro) FreeCAD.Console.PrintLog(f"Found macro {repo.name}\n") repo.url = "https://github.com/FreeCAD/FreeCAD-macros.git" utils.update_macro_installation_details(repo) self.addon_repo.emit(repo)
def retrieve_macros_from_git(self): """Retrieve macros from FreeCAD-macros.git Emits a signal for each macro in https://github.com/FreeCAD/FreeCAD-macros.git """ git = None import os try: import git except ImportError: self.info_label_signal.emit( "GitPython not installed! Cannot retrieve macros from Git") FreeCAD.Console.PrintWarning( translate( 'AddonsInstaller', 'GitPython not installed! Cannot retrieve macros from git, fallback to using the Wiki' ) + "\n") if git: git_exe = utils.checkGitBinary() try: out = os.popen(git_exe + ' --version', 'r') except: pass if 'out' in locals(): out_string = out.read() out.close() result = re.search('(\d+\.\d+\.\d+)', out_string) from distutils.version import StrictVersion git_version = StrictVersion(result.group(1)) git_version_min = StrictVersion(GITMACMIN) if git_version < git_version_min: import platform if platform.system() == 'Windows': FreeCAD.Console.PrintWarning( translate( "AddonsInstaller", "Outdated Git executable detected, consider upgrading or ensure the path to the most recent version is the first one to be found. Cannot retrieve macros from git, fallback to using the Wiki" ) + "\n") else: FreeCAD.Console.PrintWarning( translate( "AddonsInstaller", "Outdated Git binary detected, consider upgrading. Cannot retrieve macros from git, fallback to using the Wiki" ) + "\n") git = None else: self.info_label_signal.emit( "Git binary not installed! Cannot retrieve macros from Git" ) import platform if platform.system() == 'Windows': FreeCAD.Console.PrintWarning( translate( 'AddonsInstaller', 'Git executable not found. Cannot retrieve macros using git, fallback to using the Wiki' ) + "\n") else: FreeCAD.Console.PrintWarning( translate( 'AddonsInstaller', 'Git binary not found. Cannot retrieve macros using git, fallback to using the Wiki' ) + "\n") git = None if git: self.info_label_signal.emit( 'Downloading list of macros from git...') try: git.Repo.clone_from( 'https://github.com/FreeCAD/FreeCAD-macros.git', self.repo_dir) except: FreeCAD.Console.PrintWarning( translate( 'AddonsInstaller', 'Something went wrong with the Git Macro retrieval, fallback to using the Wiki' ) + "\n") return for dirpath, _, filenames in os.walk(self.repo_dir): if '.git' in dirpath: continue for filename in filenames: if filename.lower().endswith('.fcmacro'): macro = Macro(filename[:-8]) # Remove ".FCMacro". macro.on_git = True macro.src_filename = os.path.join(dirpath, filename) self.macros.append(macro)
def generate_macro(self, replacements: Dict[str, str] = {}) -> Macro: outfile = self.generate_macro_file(replacements) m = Macro("Unit Test Macro") m.fill_details_from_file(outfile) os.unlink(outfile) return m