Esempio n. 1
0
def groupPackagesInCategories(packages):
    nocategory = tr('Uncategorized').lower()
    libcategory = tr('Libraries').lower()
    othercategory = tr('Other').lower()
    categories = {}

    for pkg in packages:
        pcats = pkg.categories
        if pcats:
            if pkg.type == 'Mod' and len(
                    pcats) == 1 and pcats[0] == nocategory:
                pcats = [libcategory]

            for pcat in pcats:
                cat = categories.get(pcat)
                if not cat:
                    cat = PackageCategory(pcat)
                    categories[pcat] = cat
                cat.packages.append(pkg)

    categories = list(categories.values())
    categories.sort(
        key=lambda c: c.name.lower() if c.name != nocategory and c.name !=
        libcategory and c.name != othercategory else 'zzzz')
    return categories
Esempio n. 2
0
def get_workbench_categories_from_string(name, cats):
    if cats:
        if isinstance(cats, str):
            return [tr(c) for c in CommaStringList(cats)]
        elif isinstance(cats, list):
            return [tr(c) for c in cats]

    return predefinedCategories.get(name, [tr('Uncategorized')])
Esempio n. 3
0
def on_form_add_source(data, session):

    result = {'status': 'ok', 'validation': [], 'message': None}

    if not data.get('title'):
        result['status'] = 'error'
        result['validation'].append({
            'field': 'title',
            'message': tr('title is required')
        })

    if not data.get('url'):
        result['status'] = 'error'
        result['validation'].append({
            'field': 'url',
            'message': tr('url is required')
        })

    if not data.get('protocol'):
        result['status'] = 'error'
        result['validation'].append({
            'field': 'protocol',
            'message': tr('protocol is required')
        })

    if result['status'] != 'ok':
        result['message'] = tr('Validation error')
        return result

    name = str(hashlib.sha256(data['url'].encode()).hexdigest())
    sources = json.loads(ExtManParameters.CustomCloudSources)
    sources = [s for s in sources if s['name'] != name]

    if data.get('protocol') in ('github', 'framagit'):
        if not data['url'].endswith('.git'):
            data['url'] = data['url'].strip('/') + '.git'

    source = {
        'name': name,
        'title': data['title'],
        'description': data['description'],
        'git': data['url'],
        'protocol': data.get('protocol', 'github'),
        'type': 'Mod',
        'icon': 'html/img/package_source.svg'
    }
    sources.append(source)
    ExtManParameters.CustomCloudSources = json.dumps(sources)
    clearSourcesCache()
    return {"status": 'ok'}
Esempio n. 4
0
    def __init__(self, **kw):

        # Defaults
        self.key = None  # Package identifier
        self.name = None  # Name
        self.installDir = None  # where to install
        self.installFile = None  # for Macros: Path of installed file
        self.basePath = ""  # for Macros: full root of source file
        self.title = None  # Displayed name
        self.description = None  # description
        self.icon = None  # icon url
        self.iconSources = []  # List of alternative icons
        self.isCore = False  # True for all packages included in FreeCAD
        self.type = 'Mod'  # Mod, Macro, Workbench
        self.isGit = False  # is based on git?
        self.isWiki = False  # is based on wiki?
        self.markedAsSafe = False  # for Macros: if True, does not ask for confirm
        self.categories = [tr('Uncategorized')]  # Topics/Categories
        self.date = None  # Last update
        self.version = None  # Version
        self.git = None  # Git Repoitory URL
        self.dependencies = None  # List of dependencies
        self.homepage = None  # Web
        self.flags = {}  # py2only, obsolete, banned
        self.readmeUrl = None  # url of readme
        self.readmeFormat = 'markdown'  # markdown, mediawiki, html
        self.author = None  # Authors
        self.channelId = None  # Cloud package source channelId
        self.sourceName = None  # Cloud package source name

        # Init all with parameters
        for k, v in kw.items():
            setattr(self, k, v)
Esempio n. 5
0
def findCloudChannels():
    channels = []
    data = getSourcesData()
    for channel in data:
        channel_id = channel['id']
        channel_name = tr(channel['name'])
        sources = []
        for source in channel['sources']:
            sources.append(CloudPackageSource(source, channel_id))
        channels.append(CloudPackageChannel(channel_id, channel_name, sources))
    return channels
Esempio n. 6
0
    def __init__(self, data, channelId):
        super().__init__('Cloud:' + data['protocol'])

        self.channelId = channelId
        self.name = data['name']
        self.title = tr(data['title'])
        self.description = tr(data['description']) or data.get(
            'git', data.get('wiki', ''))
        self.protocolName = data['protocol']
        self.cacheTime = 0
        self.type = data['type']

        icon = data['icon']
        if icon.startswith('html/img/'):
            self.icon = utils.path_to_url(get_resource_path(*icon.split('/')))
        else:
            self.icon = icon

        if data['protocol'] == 'github':
            self.protocol = GithubProtocol(
                data['git'],
                data.get('git_submodules'),
                data.get('index_type'),
                data.get('index_url'),
                data.get('wiki'),
            )
        elif data['protocol'] == 'framagit':
            self.protocol = FramagitProtocol(
                data['git'],
                data.get('git_submodules'),
                data.get('index_type'),
                data.get('index_url'),
                data.get('wiki'),
            )
        elif data['protocol'] == 'fcwiki':
            self.protocol = FCWikiProtocol(data['url'], data['wiki'])
        else:
            raise UnsupportedSourceException(
                "Unsupported protocol: {0}".format(data['protocol']))

        self.updates = {}
Esempio n. 7
0
def run_macro(path, session, params, request, response):
    """
    Execute macro
    """

    path = Path(params['macro'])
    try:
        Gui.doCommandGui("exec(open(\"{0}\").read())".format(path.as_posix()))
    except Exception as ex:
        log_err(tr("Error in macro:"), path, str(ex))

    response.html_ok()
Esempio n. 8
0
    def getMacroList(self):

        macros = []
        install_dir = get_macro_path()
        default_icon = utils.path_to_url(
            get_resource_path('html', 'img', 'package_macro.svg'))

        try:
            content = http_get(self.url, timeout=45)
            if content:
                data = json.loads(content)
                wiki = get_page_content_from_json(data)

                for m_link in MACRO_LINK.finditer(wiki):

                    name = m_link.group('name').replace(' ', '_')
                    label = m_link.group('label')
                    description = m_link.group('description')

                    icon = m_link.group('icon')
                    if icon:
                        icon = self.wiki + '/Special:Redirect/file/' + icon.replace(
                            ' ', '_')
                    else:
                        icon = default_icon

                    pkg = PackageInfo(
                        key=name,
                        installDir=install_dir,
                        installFile=Path(install_dir, name + '.FCMacro'),
                        name=name,
                        title=label,
                        description=description,
                        icon=icon,
                        isCore=False,
                        type='Macro',
                        isGit=False,
                        isWiki=True,
                        markedAsSafe=False,
                        categories=[tr('Uncategorized')],
                        date=None,
                        version=None,
                        readmeUrl='{0}/Macro_{1}?origin=*'.format(
                            self.wiki, name),
                        readmeFormat='html')
                    flags.apply_predefined_flags(pkg)
                    macros.append(pkg)

        except:
            traceback.print_exc(file=sys.stderr)

        return macros
Esempio n. 9
0
class ExtManWorkbench(Gui.Workbench):
    """Extension Manager Workbench"""

    Icon = str(get_resource_path('icons', 'ExtManWorkbench.svg'))
    MenuText = tr("Extension Manager")
    ToolTip = tr("Extension Manager")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def GetClassName(self):
        return "Gui::PythonWorkbench"

    def Initialize(self):
        log("ExtMan Initialized")

    def Activated(self):
        install_router(create_router())
        start_browser()

    def Deactivated(self):
        pass
Esempio n. 10
0
def start_browser():
    global __browser_instance__
    if not __browser_instance__:
        main_window = Gui.getMainWindow().findChild(QtGui.QMdiArea)
        bi = WebView(tr('Extension Manager'), get_cache_path(),
                     request_handler, message_handler, main_window)
        bi.closed.connect(on_web_view_close)
        index = path_to_extman_url(get_resource_path('html', 'index.html'))
        bi.load(index)
        main_window.addSubWindow(bi)
        bi.show()
        __browser_instance__ = bi
    return __browser_instance__
Esempio n. 11
0
 def eval_expr(match):
     try:
         etype = match.group(1)
         eexpr = match.group(2)
         # Translate shortcut
         if etype == 't:':
             return tr(eexpr)
         # Eval Expression
         elif etype == 'e:':
             return compile_and_execute(eexpr, model, 'eval')
         # Execute Statement
         elif etype == 'x:':
             return compile_and_execute(eexpr, model, 'exec')
         # Resolve local symbol
         else:
             return str(
                 model.get(eexpr, '???{0}{1}???'.format(etype, eexpr)))
     except:  # Catch All Errors/Exceptions
         log(traceback.format_exc())
         log("Error executing expression {0} in template {1}".format(
             eexpr, path))
         return 'Error:' + traceback.format_exc()
Esempio n. 12
0
    def installMacro(self, pkg):

        result = InstallResult()
        url = self.getWikiPageUrlJson("Macro_{0}".format(quote(pkg.name)))
        content = http_get(url)

        # Manage mediawiki redirects
        m = REDIRECT.search(content)
        max_redirects = 3
        while m:
            url = self.getWikiPageUrlJson("{0}".format(quote(m.group('link'))))
            content = http_get(url)
            m = REDIRECT.search(content)
            max_redirects -= 1
            if max_redirects <= 0:
                break

        if not content:
            result.message = tr(
                """This macro contains invalid content, it cannot be installed directly by the 
                Extension Manager""")
        else:
            wikitext = get_page_content_from_json(json.loads(content))

            # Try {{MacroCode ...}}
            m = MACRO_CODE.search(wikitext)
            if not m:
                # Try <pre> ... </pre>
                m = LEGACY_MACRO_CODE.search(wikitext)

            # Code in wiki
            if m:
                try:
                    f = open(pkg.installFile, 'w', encoding='utf-8')
                except IOError as ex:
                    result.message = str(ex)
                else:
                    with f:
                        try:
                            f.write(m.group('code'))
                            result.ok = True
                        except:
                            result.message = tr(
                                """This macro contains invalid content, 
                                it cannot be installed directly by the Extension Manager"""
                            )

            # Try external source
            else:
                m = MACRO_CODE_EXTLINK.search(wikitext)
                if m:
                    pre = tr("This macro must be downloaded from this link")
                    pos = tr(
                        """Copy the link, download it and install it manually 
                        or follow instructions from the external resource""")
                    result.message = """{0}: 
                        <textarea class="form-control" style="min-height: 100px; margin: 5px;" readonly>{1}
                        </textarea>
                        {2}""".format(pre, m.group('link'), pos)

        return result
Esempio n. 13
0
# *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
# *  GNU General Public License for more details.                           *
# *                                                                         *
# *  You should have received a copy of the GNU General Public License      *
# *  along with this program.  If not, see <https://www.gnu.org/licenses/>. *
# *                                                                         *
# ***************************************************************************
# noinspection PyPep8Naming

import os
from urllib.parse import quote

from freecad.extman import tr
from freecad.extman.template.html_utils import get_resource_url, Components

TR_RUN = tr('Run')
TR_CLOSE = tr('Close')
TR_EDIT = tr('Edit')
TR_ACTIVATE = tr('Activate')
TR_UPDATE = tr('Update')
TR_CORE_PACKAGE = tr('Core Package')
TR_COMMUNITY_PACKAGE = tr('Community Package')
TR_WORKBENCH = tr('Workbench')
TR_MACRO = tr('Macro')
TR_MODULE = tr('Module')
TR_INSTALLED = tr('Installed')
TR_GIT = tr('Git')
TR_WIKI = tr('Wiki')
TR_FLAG_OBSOLETE = tr('Obsolete package')
TR_FLAG_PY2ONLY = tr('Python2 only')
TR_README = tr('readme')
Esempio n. 14
0
 def getTitle(self):
     return tr('Installed packages')
Esempio n. 15
0
def get_workbench_categories(wb):
    if wb and hasattr(wb, 'Categories'):
        return wb.Categories
    else:
        return predefinedCategories.get(wb.__class__.__name__,
                                        [tr('Uncategorized')])
Esempio n. 16
0
    "A2plus": "a2pWorkbench",
    "ArchTextures": "ArchTextureWorkbench",
    "cadquery_module": "CadQueryWorkbench",
    "Defeaturing": "DefeaturingWB",
    "kicadStepUpMod": "KiCadStepUpWB",
    "Manipulator": "ManipulatorWB",
    "Part-o-magic": "PartOMagicWorkbench",
    "sheetmetal": "SMWorkbench",
    "FCGear": "gearWorkbench",
    "frame": "frame_Workbench",
    'CurvedShapes': "CurvedShapesWB",
    "None": None
}

predefinedCategories = {
    "ArchWorkbench": [tr("Architecture")],
    "CompleteWorkbench": [tr("Other")],
    "DraftWorkbench": [tr("CAD/CAM")],
    "DrawingWorkbench": [tr("CAD/CAM")],
    "FemWorkbench": [tr("Analysis")],
    "ImageWorkbench": [tr("Other")],
    "InspectionWorkbench": [tr("Analysis")],
    "MeshWorkbench": [tr("3D")],
    "OpenSCADWorkbench": [tr("CAD/CAM")],
    "PartWorkbench": [tr("CAD/CAM")],
    "PartDesignWorkbench": [tr("CAD/CAM")],
    "PathWorkbench": [tr("CAD/CAM")],
    "PointsWorkbench": [tr("CAD/CAM")],
    "RaytracingWorkbench": [tr("3D")],
    "ReverseEngineeringWorkbench": [tr("Engineering")],
    "RobotWorkbench": [tr("Engineering")],
Esempio n. 17
0
 def getDescription(self):
     return tr('All installed packages')
Esempio n. 18
0
def build_macro_package(path,
                        macro_name,
                        is_core=False,
                        is_git=False,
                        is_wiki=False,
                        install_path=None,
                        base_path=""):

    with open(path, 'r', encoding='utf-8') as f:

        try:
            tags = get_macro_tags(f.read(), path)
        except:  # !TODO: Handle encoding problems in old windows platforms
            tags = {k: None for k in MACRO_TAG_FILTER}
            log_err(tr('Macro {0} contains invalid characters').format(path))

        install_dir = get_macro_path()
        base = dict(key=str(install_path) if install_path else str(path),
                    type='Macro',
                    isCore=is_core,
                    installDir=install_dir,
                    installFile=Path(install_dir, path.name),
                    isGit=is_git,
                    isWiki=is_wiki,
                    basePath=base_path)
        tags.update(base)

        if not tags['title']:
            tags['title'] = tags['name'] or macro_name

        tags['name'] = macro_name  # Always override name with actual file name

        if not tags['icon']:
            tags['icon'] = get_resource_path('html', 'img',
                                             'package_macro.svg')

        try:
            if not Path(tags['icon']).exists():
                tags['icon'] = get_resource_path('html', 'img',
                                                 'package_macro.svg')
        except:
            tags['icon'] = get_resource_path('html', 'img',
                                             'package_macro.svg')

        tags['icon'] = utils.path_to_url(tags['icon'])

        if tags['comment']:
            tags['description'] = tags['comment']

        if not tags['description']:
            tags['description'] = tr('Warning! No description')

        if tags['categories']:
            cats = COMMA_SEP_LIST_PATTERN.split(tags['categories'])
            tags['categories'] = [tr(c) for c in cats]
        else:
            tags['categories'] = [tr('Uncategorized')]

        if tags['files']:
            tags['files'] = COMMA_SEP_LIST_PATTERN.split(tags['files'])

        if tags['readme']:
            tags['readmeUrl'] = tags['readme']
            tags['readmeFormat'] = 'html'
        elif tags['wiki']:
            tags['readmeUrl'] = tags['wiki']
            tags['readmeFormat'] = 'html'
        elif tags['web']:
            tags['readmeUrl'] = tags['web']
            tags['readmeFormat'] = 'html'

        return PackageInfo(**tags)
Esempio n. 19
0
    def installMacro(self, pkg):

        (git_available, _, git_version, git_python,
         git_version_ok) = install_info()

        # Initialize result
        result = InstallResult(gitAvailable=git_available,
                               gitPythonAvailable=git_python is not None,
                               zipAvailable=zlib.is_zip_available(),
                               gitVersionOk=git_version_ok,
                               gitVersion=git_version)

        # Ensure last version if available locally
        src_dir = self.downloadMacroList()

        # Get path of source macro file
        src_file = Path(src_dir, pkg.basePath, pkg.installFile.name)

        # Copy Macro
        files = []
        try:

            macros_dir = get_macro_path()
            if not macros_dir.exists():
                macros_dir.mkdir(parents=True)

            log('Installing', pkg.installFile)

            shutil.copy2(src_file, pkg.installFile)
            files.append(pkg.installFile)

            # Copy files
            if pkg.files:
                for f in pkg.files:

                    file_base_path = utils.path_relative(f)
                    dst = Path(pkg.installDir, file_base_path).absolute()
                    src = Path(src_dir, pkg.basePath,
                               file_base_path).absolute()

                    log('Installing ', dst)

                    if pkg.installDir not in dst.parents:
                        result.message = tr(
                            'Macro package attempts to install files outside of permitted path'
                        )
                        raise Exception()

                    if src_dir not in src.parents:
                        result.message = tr(
                            'Macro package attempts to access files outside of permitted path'
                        )
                        raise Exception()

                    dst_dir = dst.parent
                    if dst_dir != pkg.installDir and dst_dir not in files and not dst_dir.exists(
                    ):
                        dst_dir.mkdir(parents=True)
                        files.append(dst_dir)

                    shutil.copy2(src, dst)
                    files.append(dst)

            result.ok = True

        except:

            log(traceback.format_exc())

            result.ok = False
            if not result.message:
                result.message = tr(
                    'Macro was not installed, please contact the maintainer.')

            # Rollback
            files.sort(reverse=True)
            for f in files:
                try:
                    log("Rollback ", f)
                    if f.is_file():
                        f.unlink()
                    elif f.is_dir():
                        shutil.rmtree(f, ignore_errors=True)
                except:
                    log(traceback.format_exc())

        return result