def download(self, folder=None):
     folder = folder or get_skills_folder()
     if self.download_url.endswith(".tar.gz"):
         ext = "tar.gz"
     elif "zipball" in self.download_url:
         ext = "zip"
     else:
         ext = self.download_url.split(".")[-1]
     file = self.skill_folder + "." + ext
     url = self.download_url
     return install_skill(url,
                          folder,
                          file,
                          session=requests,
                          skill_folder_name=self.uuid)
Example #2
0
def get_local_skills(parse_github: bool = False,
                     skiplist: Optional[list] = None):
    try:
        skills = get_skills_folder()
    except FileNotFoundError:
        return
    except KeyError:
        # TODO: Patching config error in ovos_utils
        return
    skiplist = skiplist or []
    folders = listdir(skills)
    for fold in folders:
        path = join(skills, fold)
        if not isdir(path) or fold in skiplist:
            continue

        skill_dir = join(skills, fold)
        skill = get_skill_data_from_directory(skill_dir)
        yield SkillEntry.from_json(skill, parse_github=parse_github)
 def download(self, folder: str = None) -> bool:
     folder = folder or get_skills_folder()
     if self.download_url.endswith(".tar.gz"):
         ext = "tar.gz"
     elif "zipball" in self.download_url:
         ext = "zip"
     else:
         ext = self.download_url.split(".")[-1]
     file = self.skill_folder + "." + ext
     url = self.download_url
     skill_dirname = self.uuid
     if not skill_dirname:
         raise SkillEntryError(
             f"OSM installation of {self.skill_name or 'unknown skill'} failed!"
             f" uuid was not defined.")
     return install_skill(url,
                          folder,
                          file,
                          session=requests,
                          skill_folder_name=skill_dirname)
    def __init__(self, platform='default', old_skills_dir=None,
                 skills_dir=None, repo=None, versioned=True):
        self.platform = platform

        # Keep this variable alive for a while, is used to move skills from the
        # old config based location to XDG
        self.old_skills_dir = path.expanduser(old_skills_dir or '') or None
        self.skills_dir = (skills_dir or get_skills_folder())

        self.repo = repo or SkillRepo()
        self.versioned = versioned
        self.lock = MsmProcessLock()

        # Property placeholders
        self._all_skills = None
        self._default_skills = None
        self._local_skills = None
        self._device_skill_state = None

        self.saving_handled = False
        self.device_skill_state_hash = ''
        with self.lock:
            self._init_skills_data()
Example #5
0
def get_local_skills(parse_github=False, skiplist=None):
    skills = get_skills_folder()
    skiplist = skiplist or []
    folders = listdir(skills)
    for fold in folders:
        path = join(skills, fold)
        if not isdir(path) or fold in skiplist:
            continue

        skill = {
            "appstore": "InstalledSkills",
            "appstore_url": skills,
            "skill_id": fold,
            "foldername": fold,
            "requirements": {
                "python": [],
                "system": [],
                "skill": []
            }
        }

        # if installed by msm/osm will obey this convention
        if "." in fold:
            try:
                repo, author = fold.split(".")
                skill["skillname"] = repo
                skill["authorname"] = author
                skill["url"] = f'https://github.com/{author}/{repo}'
            except:  # TODO replace with some clever check ?
                pass

        # parse git info
        gitinfo = join(path, ".git/config")
        if isfile(gitinfo):
            with open(gitinfo) as f:
                for l in f.readlines():
                    if l.strip().startswith("url ="):
                        skill["url"] = l.split("url =")[-1].strip()
                        skill["authorname"], skill["skillname"] = \
                            author_repo_from_github_url(skill["url"])
                    if l.strip().startswith("[branch "):
                        skill["branch"] = l.split("branch")[-1]\
                            .replace('"', "").strip()

        for rtdir, foldrs, files in walk(join(skills, fold)):
            for f in files:
                if f in GITHUB_JSON_FILES:
                    with open(join(rtdir, f)) as fi:
                        skill_meta = json.load(fi)
                    skill = merge_dict(skill, skill_meta, merge_lists=True)
                elif f in GITHUB_README_FILES:
                    with open(join(rtdir, f)) as fi:
                        readme = readme_to_json(fi.read())
                    skill = merge_dict(skill,
                                       readme,
                                       new_only=True,
                                       merge_lists=True)
                elif f in GITHUB_DESKTOP_FILES:
                    skill['desktopFile'] = True
                elif f in GITHUB_ICON_FILES:
                    skill["icon"] = join(rtdir, f)
                elif f in GITHUB_LICENSE_FILES:
                    with open(join(rtdir, f)) as fi:
                        lic = fi.read()
                    skill["license"] = parse_license_type(lic)
                elif f in GITHUB_LOGO_FILES:
                    skill["logo"] = join(rtdir, f)
                elif f in GITHUB_MANIFEST_FILES:
                    with open(join(rtdir, f)) as fi:
                        manifest = validate_manifest(fi.read())
                    skill["requirements"]["python"] += manifest.get(
                        "python") or []
                    skill["requirements"]["system"] += manifest.get(
                        "system") or []
                    skill["requirements"]["skill"] += manifest.get(
                        "skill") or []
                elif f in GITHUB_REQUIREMENTS_FILES:
                    with open(join(rtdir, f)) as fi:
                        reqs = [r for r in fi.read().split("\n") if r.strip()]
                    skill["requirements"]["python"] += reqs
                elif f in GITHUB_SKILL_REQUIREMENTS_FILES:
                    with open(join(rtdir, f)) as fi:
                        reqs = [r for r in fi.read().split("\n") if r.strip()]
                    skill["requirements"]["skill"] += reqs
        yield SkillEntry.from_json(skill, parse_github=parse_github)
 def is_previously_installed(self, folder=None):
     folder = folder or get_skills_folder()
     return isdir(join(folder, self.uuid))
 def is_previously_installed(self, folder=None):
     folder = folder or get_skills_folder()
     # TODO If self.uuid is None, this skill entry is somehow malformed,
     # probably because it was created manually with partial input.
     # Something should happen in this case, but what?
     return isdir(join(folder, self.uuid)) if self.uuid else False
    def install(self,
                folder: Optional[str] = None,
                default_branch: str = "master",
                platform: Optional[str] = None,
                update: bool = True) -> bool:
        if not folder:
            folder = get_skills_folder()
        if not update and self.is_previously_installed(folder):
            return False
        if self.branch_overrides:
            try:
                platform = platform or detect_enclosure()
            except Exception as e:
                LOG.error("Failed to detect platform")
                raise e
            if platform in self.branch_overrides:
                branch = self.branch_overrides[platform]
                if branch != self.branch:
                    LOG.info("Detected platform specific branch:" + branch)
                    skill = SkillEntry.from_github_url(self.url, branch)
                    return skill.install(folder, default_branch)

        LOG.info("Installing skill: {url} from branch: {branch}".format(
            url=self.url, branch=self.branch))

        skills = self.requirements.get("skill", [])
        if skills:
            LOG.info('Installing required skills')
        for s in skills:
            skill = SkillEntry.from_github_url(s)
            skill.install(folder, default_branch)

        system = self.requirements.get("system")
        if system:
            LOG.info('Installing system requirements')
            install_system_deps(system)

        pyth = self.requirements.get("python")
        if pyth:
            LOG.info('Running pip install')
            pip_install(pyth)

        LOG.info("Downloading " + self.url)
        updated = self.download(folder)
        # TODO: desktop file generation has been disabled for the time being
        '''
        if self.json.get("desktopFile"):
            LOG.info("Creating desktop entry")
            # TODO support system wide? /usr/local/XXX ?
            desktop_dir = expanduser("~/.local/share/applications")
            icon_dir = expanduser("~/.local/share/icons")
            # ensure directories exist
            if not exists(desktop_dir):
                mkdir(desktop_dir)
            if not exists(icon_dir):
                mkdir(icon_dir)

            # copy the files to a unique path, this way duplicate file names
            # dont overwrite each other, eg, several skills with "icon.png"
            base_name = ".".join([self.skill_folder, self.skill_author]).lower()

            # copy icon file
            icon_file = join(icon_dir,
                             base_name + "." + self.skill_icon.split(".")[-1])
            if self.skill_icon.startswith("http"):
                content = requests.get(self.skill_icon).content
                with open(icon_file, "wb") as f:
                    f.write(content)
            elif isfile(self.skill_icon):
                shutil.copyfile(self.skill_icon, icon_file)

            # copy .desktop file
            desktop_file = join(desktop_dir, base_name + ".desktop")
            with open(desktop_file, "w") as f:
                f.write(self.desktop_file)
            '''
        return updated