Esempio n. 1
0
def plugin_components(plugin_name, sub_category=None):
    """Get all of the components of a Ladybug Tools Plugin from the component server.

    Args:
        plugin_name: Text for the name of a particular plugin (aka. insect) to
            place components from (eg. "Ladybug", "Honeybee", "HB-Energy").
        sub_category: Text for a specific plugin sub-category (aka. tab) to
            be exported (eg. "1 :: Analyze Data"). If None, all components in
            the plugin will be places on the canvas. (Default: None).

    Returns:
        A dictionary of the plugin components with the name of the component as
        the key and the component object as the value.
    """
    # loop through the component server and find all the components in the plugin
    components = {}
    for proxy in ghi.ComponentServer.ObjectProxies:
        if proxy.Obsolete:
            continue
        category = proxy.Desc.Category
        subcategory = proxy.Desc.SubCategory
        # check to see if the component is in the plugin
        if category.strip() == plugin_name:  # if so, see if it is in the sub category
            if sub_category is None or subcategory.strip() == sub_category:
                if str(proxy.Kind) == 'CompiledObject':  # it's a .gha
                    components[proxy.Desc.Name] = proxy.CreateInstance()
                elif str(proxy.Kind) == 'UserObject':  # it's a .ghuser
                    components[proxy.Desc.Name] = \
                        gh.GH_UserObject(proxy.Location).InstantiateObject()
    return components
Esempio n. 2
0
def current_userobject_version(component):
    """Get the current installed version of a component.

    Args:
        component: A Grasshopper Python component with the same name as an
            installed user object. If no matching user object is found, this
            method returns None.
    """
    # load component from the folder where it should be
    assert component.Category in FOLDER_MAP, \
        'Unknown category: %s. Add category to folder_dict.' % component.Category
    fp = os.path.join(UO_FOLDER, FOLDER_MAP[component.Category],
                      'user_objects', '%s.ghuser' % component.Name)

    if os.path.isfile(fp):  # if the component was found, parse out the version
        uo = gh.GH_UserObject(fp).InstantiateObject()
        # uo.Message returns None so we have to find it the old school way!
        for lc, line in enumerate(uo.Code.split('\n')):
            if lc > 200:  # this should never happen for valid userobjects
                raise ValueError(
                    'Failed to find version from UserObject for %s' % uo.Name)
            if line.strip().startswith("ghenv.Component.Message"):
                return line.split("=")[1].strip()[1:-1]
    else:  # there is no currently installed version of this userobject
        return None
Esempio n. 3
0
def create_userobject(component, move=True):
    """Create UserObject from a component.

    Args:
        component: A Grasshopper Python component.
        move: A Boolean to note whether the component should be moved to a subdirectory
            based on FOLDER_MAP. (Default: True).
    """
    # initiate userobject
    uo = gh.GH_UserObject()
    # set attributes
    uo.Icon = component.Icon_24x24
    try:
        exposure = int(component.AdditionalHelpFromDocStrings)
    except Exception:  # no exposure category specified
        exposure = 1
    uo.Exposure = EXPOSURE_MAP[exposure]
    uo.BaseGuid = component.ComponentGuid
    uo.Description.Name = component.Name
    uo.Description.Description = component.Description
    uo.Description.Category = component.Category
    uo.Description.SubCategory = component.SubCategory

    # save the userobject to a file
    uo.SetDataFromObject(component)
    uo.SaveToFile()

    # move the user object file to the assigned folder
    if move:
        ufd = os.path.join(UO_FOLDER, FOLDER_MAP[component.Category], 'user_objects')
        ufp = os.path.join(ufd, '%s.ghuser' % component.Name)
        if not os.path.isdir(ufd):
            # create folder if it is not already created
            os.mkdir(ufd)
        elif os.path.isfile(ufp):
            # remove current userobject
            try:
                os.remove(ufp)
            except Exception:
                pass  # access is denied to the user object location
        uo.Path = ufp

    uo.SaveToFile()
    return uo
Esempio n. 4
0
def create_userobject(component, move=True):
    """Create UserObject from a component.
    
    Args:
        component: A Grasshopper Python component.
        move: A Boolean to move the component a subdirectory based on
            folder_dict.
    """
    # initiate userobject
    uo = gh.GH_UserObject()
    # set attributes
    uo.Icon = component.Icon_24x24
    try:
        exposure = int(component.AdditionalHelpFromDocStrings)
    except:
        expousre = 1
    uo.Exposure = exposure_dict.get(exposure, 1)
    uo.BaseGuid = component.ComponentGuid
    uo.Description.Name = component.Name
    uo.Description.Description = component.Description
    uo.Description.Category = component.Category
    uo.Description.SubCategory = component.SubCategory

    # save the userobject
    uo.SetDataFromObject(component)
    uo.SaveToFile()

    # move to the assigned folder
    if move:
        ufd = os.path.join(UOFOLDER, folder_dict[comp.Category],
                           'user_objects')
        ufp = os.path.join(ufd, '%s.ghuser' % comp.Name)
        if not os.path.isdir(ufd):
            # create folder if it is not already created
            os.mkdir(ufd)
        elif os.path.isfile(ufp):
            # remove current userobject
            os.remove(ufp)
        uo.Path = ufp

    uo.SaveToFile()
    return uo
Esempio n. 5
0
def get_current_version(comp):
    """Find the current userobject with the same name and get its version."""

    # load component from possible folder
    assert comp.Category in folder_dict, \
        'Unknown category: %s. Add category to folder_dict.' % comp.Category

    fp = os.path.join(UOFOLDER, folder_dict[comp.Category], 'user_objects',
                      '%s.ghuser' % comp.Name)

    if os.path.isfile(fp):
        uo = gh.GH_UserObject(fp).InstantiateObject()
        # uo.Message returns None so we have to find it the old school way!
        for lc, line in enumerate(uo.Code.split('\n')):
            if lc > 200:
                # this should never happen for valid userobjects
                raise ValueError(
                    'Failed to find version from UserObject for %s' % uo.Name)
            if line.strip().startswith("ghenv.Component.Message"):
                return line.split("=")[1].strip()[1:-1]
    else:
        # this is no previous version of this userobject
        return None
Esempio n. 6
0
def sync_component(component, syncing_component):
    """Sync a component on the canvas with its corresponding installed version.

    This includes identifying if the component by name in the user object folder,
    injecting the code from that user object into the component, and (if the
    component inputs or outputs have changed) circling the component in red +
    dropping the new user object next to the component.

    Args:
        component: A Grasshopper component object on the canvas to be circled.
        syncing_component: An object for the component that is doing the syncing.
            This will be used to give warnings and access the Grasshopper doc.
            Typically, this can be accessed through the ghenv.Component call.
    """
    # identify the correct user object sub-folder to which the component belongs
    ghuser_file = '%s.ghuser' % component.Name
    if str(component.Name).startswith(('LB', 'HB', 'DF')):
        fp = os.path.join(UO_FOLDER, FOLDER_MAP[component.Category],
                          'user_objects', ghuser_file)
    elif str(component.Name).startswith(
        ('Ladybug', 'Honeybee', 'HoneybeePlus')):
        category = str(component.Name).split('_')[0]
        fp = os.path.join(UO_FOLDER, category, ghuser_file)
    else:  # unidentified plugin; see if we can find it in the root
        fp = os.path.join(UO_FOLDER, ghuser_file)

    # check to see if the user object is installed
    if not os.path.isfile(fp):  # see if there's a folder for the category
        if component.Category in FOLDER_MAP:
            fp = os.path.join(UO_FOLDER, FOLDER_MAP[component.Category],
                              ghuser_file)
        if not os.path.isfile(fp):  # see if the component is in the root
            fp = os.path.join(UO_FOLDER, ghuser_file)
            if not os.path.isfile(
                    fp):  # all hope is lost; component not installed
                warning = 'Failed to find the userobject for %s' % component.Name
                give_warning(syncing_component, warning)
                return False

    # the the instance of the user object from the file
    uo = gh.GH_UserObject(fp).InstantiateObject()

    # check to see if the version of the userobject has changed
    if not has_version_changed(uo, component):
        return False

    # the version has changed, let's update the code
    component.Code = uo.Code
    doc = syncing_component.OnPingDocument()  # get the Grasshopper document

    # define the callback function and update the solution
    def call_back(document):
        component.ExpireSolution(False)

    doc.ScheduleSolution(2, gh.GH_Document.GH_ScheduleDelegate(call_back))

    # check if the inputs or outputs have changed
    if input_output_changed(uo, component):
        insert_new_user_object(uo, component, doc)
        mark_component(doc,
                       component)  # mark component with a warning to the user
        return 'Cannot update %s. Replace manually.' % component.Name

    return 'Updated %s' % component.Name
Esempio n. 7
0
def exportToUserObject(component, targetFolder, lb_preparation):
    targetFolder = os.path.join(targetFolder, "userObjects")
    if not os.path.isdir(targetFolder): os.mkdir(targetFolder)

    def isNewerVersion(currentUO, component):
        # check if the component has a newer version than the current userObjects
        # version of the connected component
        if component.Message == None: return True
        if len(component.Message.split("\n")) < 2: return True

        ghVersion, ghDate = component.Message.split("\n")
        ghCompVersion = map(int, ghVersion.split("VER ")[1].split("."))
        month, day, ghYear = ghDate.split("_")
        # print version, date
        month = lb_preparation.monthList.index(month.upper()) + 1
        ghCompDate = int(lb_preparation.getJD(month, day))

        # in case there was no date for the userobject
        # the file will be considered older and will be overwrittern
        ghComponent = currentUO.InstantiateObject()
        # this is not the best way but works for now!
        # should be a better way to compute the component and get the message
        componentCode = ghComponent.Code.split("\n")

        UODate = ghCompDate - 1
        # version of the file
        for lineCount, line in enumerate(componentCode):
            if lineCount > 200: break
            if line.strip().startswith("ghenv.Component.Message"):
                #print line
                # print line.split("=")[1].strip().split("\n")
                version, date = line.split("=")[1].strip().split("\\n")

                # in case the file doesn't have an standard Dragonfly message let it be updated
                try:
                    UOVersion = map(int, version.split("VER ")[1].split("."))
                except:
                    return True
                month, day, UOYear = date.split("_")

                # should find the reason and fix it later
                if month == "SEPT": month = "SEP"

                month = lb_preparation.monthList.index(month.upper()) + 1
                UODate = int(lb_preparation.getJD(month, day))
                break

        # check if the version of the code is newer
        try:
            if int(ghYear.strip()) > int(UOYear[:-1].strip()):
                return True
            elif ghCompDate > UODate:
                return True
            elif ghCompDate == UODate:
                for ghVer, UOVer in zip(UOVersion, UOVersion):
                    if ghVer < UOVer: return False
                return True
            else:
                print "\nThere is a newer userObject in Grasshopper folder that will be copied: " + currentUO.Path + "." + \
                      "\nUserObject version is: " +  version + " " + date + \
                      "\nThe component version is: "  +  ghVersion + " " + ghDate + ".\n"

                return False
        except:
            return True

    # check if the userObject is already existed in the folder
    try:
        filePath = os.path.join(UOFolder, component.Name + ".ghuser")
        currentUO = gh.GH_UserObject(filePath)
    except:
        # the userobject is not there so just create it
        currentUO = None

    if currentUO != None:
        # if is newer remove
        if isNewerVersion(currentUO, component):
            # it has a newer version so let's remove the old one and creat a new userobject
            pass
            if not component.Category == "Maths":
                removeNicely = cs.RemoveCachedObject(filePath)
                if not removeNicely: os.remove(filePath)
        else:
            # there is already a newer version so just copy that to the folder instead
            # and return
            dstFullPath = os.path.join(targetFolder,
                                       component.Name + ".ghuser")
            shutil.copy2(filePath, dstFullPath)
            return

    # create the new userObject in Grasshopper folder
    uo = gh.GH_UserObject()
    uo.Icon = component.Icon_24x24

    try:
        uo.Exposure = exposureDict[int(component.AdditionalHelpFromDocStrings)]
    except:
        try:
            compCode = component.Code
            # this is so dirty
            exposureNumber = compCode.split(
                "ghenv.Component.AdditionalHelpFromDocStrings")[1].split(
                    "\n")[0].replace("=", "").replace('"', "").strip()
            uo.Exposure = exposureDict[int(exposureNumber)]

        except:
            uo.Exposure = exposureDict[int(1)]

    uo.BaseGuid = component.ComponentGuid
    uo.Description.Name = component.Name
    uo.Description.Description = component.Description

    # if user hasn't identified the category then put it into honeybee as an unknown!
    if component.Category == "Maths":
        uo.Description.Category = "Honeybee"
    else:
        uo.Description.Category = component.Category

    if component.SubCategory == "Script":
        uo.Description.SubCategory = "UnknownBees"
    else:
        uo.Description.SubCategory = component.SubCategory

    uo.CreateDefaultPath(True)
    uo.SetDataFromObject(component)
    uo.SaveToFile()

    # copy into Dragonfly
    filePathInit = os.path.join('\\'.join(filePath.split('\\')[:-2]),
                                component.Name + ".ghuser")
    shutil.copy2(filePathInit, filePath)
    os.remove(filePathInit)

    # copy the component over
    dstFullPath = os.path.join(targetFolder, component.Name + ".ghuser")
    shutil.copy2(filePath, dstFullPath)

    gh.GH_ComponentServer.UpdateRibbonUI()

    print "UserObject successfully added to: "
Esempio n. 8
0
     # check if the version of the code is newer
     if int(ghYear.strip()) < int(UOYear[:-1].strip()):
             return True, ghComponent.Code
     elif ghCompDate < UODate:
         return True, ghComponent.Code
     elif ghCompDate == UODate:
         for ghVer, UOVer in zip(UOVersion, UOVersion):
             if ghVer > UOVer: return False, " "
         return True, ghComponent.Code
     else:
         return False, " "
 
 # check if the userObject is already existed in the folder
 try:
     filePath = os.path.join(newUOFolder, component.Name + ".ghuser")
     newUO = gh.GH_UserObject(filePath)
 except:
     # there is no newer userobject with the same name so just return
     return
 
 # if is newer remove
 isNewer, newCode = isNewerVersion(newUO, component)
 # replace the code inside the component with userObject code
 if isNewer:
     if component.CodeInputParam == None:
         component.Code = newCode
         component.ExpireSolution(True)
     else:
         warning = "Failed to update %s. Remove code input from the component and try again!"%component.Name
         print warning
         ghenv.Component.AddRuntimeMessage(gh.GH_RuntimeMessageLevel.Warning, warning)
Esempio n. 9
0
def update_component(component, uofolder):
    """Update a component using its version in the user object folder."""

    # identify the correct user object sub-folder to which the component belongs
    if str(component.Name).startswith('LB'):  # ladybug [+]
        fp = os.path.join(uofolder, 'ladybug_grasshopper', 'user_objects',
                          '%s.ghuser' % component.Name)
    elif str(component.Name).startswith('HB'):  # honeybee[+]
        if str(component.Category) == 'Honeybee':
            fp = os.path.join(uofolder, 'honeybee_grasshopper_core',
                              'user_objects', '%s.ghuser' % component.Name)
        elif str(component.Category) == 'HB-Energy':
            fp = os.path.join(uofolder, 'honeybee_grasshopper_energy',
                              'user_objects', '%s.ghuser' % component.Name)
        elif str(component.Category) == 'HB-Radiance':
            fp = os.path.join(uofolder, 'honeybee_grasshopper_radiance',
                              'user_objects', '%s.ghuser' % component.Name)
    elif str(component.Name).startswith('DF'):  # dragonfly [+]
        fp = os.path.join(uofolder, 'dragonfly_grasshopper', 'user_objects',
                          '%s.ghuser' % component.Name)
    elif str(component.Name).startswith('Ladybug'):  # ladybug legacy
        fp = os.path.join(uofolder, 'Ladybug', '%s.ghuser' % component.Name)
    elif str(component.Name).startswith('Honeybee'):  # honeybee legacy
        fp = os.path.join(uofolder, 'Honeybee', '%s.ghuser' % component.Name)
    elif str(component.Name).startswith('HoneybeePlus'):  # old honeybee [+]
        fp = os.path.join(uofolder, 'HoneybeePlus',
                          '%s.ghuser' % component.Name)
    else:  # unidentified plugin; see if we can find it in the root
        fp = os.path.join(uofolder, '%s.ghuser' % component.Name)
        if not os.path.isfile(fp):
            category = str(component.Name).split('_')[0]
            fp = os.path.join(uofolder, category, '%s.ghuser' % component.Name)

    if not os.path.isfile(fp):
        warning = 'Failed to find the userobject for %s' % component.Name
        give_warning(ghenv.Component, warning)
        return False

    # the the instance of the user object
    uo = gh.GH_UserObject(fp).InstantiateObject()

    # check to see if the version of the userobject has changed
    if not has_version_changed(uo, component):
        return False

    # the version has changed
    component.Code = uo.Code

    # define the callback function
    def call_back(document):
        component.ExpireSolution(False)

    # update the solution
    doc.ScheduleSolution(2, gh.GH_Document.GH_ScheduleDelegate(call_back))

    # check if the inputs or outputs have changed
    if input_output_changed(uo, component):
        insert_new_uo(uo, component, doc)
        mark_component(doc,
                       component)  # mark component with a warning to the user
        return 'Cannot update %s. Replace manually.' % component.Name

    return 'Updated %s' % component.Name