Skip to content

genericcomps

Generic extension components.

Attributes

mlogger = coreutils.logger.get_logger(__name__) module-attribute

EXT_DIR_KEY = 'directory' module-attribute

SUB_CMP_KEY = 'components' module-attribute

LAYOUT_ITEM_KEY = 'layout_items' module-attribute

LAYOUT_DIR_KEY = 'directive' module-attribute

TYPE_ID_KEY = 'type_id' module-attribute

NAME_KEY = 'name' module-attribute

Classes

TypedComponent

Bases: object

Component with a type id.

Attributes

type_id = None class-attribute instance-attribute

CachableComponent

Bases: TypedComponent

Cacheable Component.

Attributes

type_id = None class-attribute instance-attribute

Functions

get_cache_data()
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def get_cache_data(self):
    cache_dict = self.__dict__.copy()
    if hasattr(self, TYPE_ID_KEY):
        cache_dict[TYPE_ID_KEY] = getattr(self, TYPE_ID_KEY)
    return cache_dict
load_cache_data(cache_dict)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def load_cache_data(self, cache_dict):
    for k, v in cache_dict.items():
        self.__dict__[k] = v

LayoutDirective(directive_type=None, target=None)

Bases: CachableComponent

Layout directive.

Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def __init__(self, directive_type=None, target=None):
    self.directive_type = directive_type
    self.target = target

Attributes

type_id = None class-attribute instance-attribute
directive_type = directive_type instance-attribute
target = target instance-attribute

Functions

get_cache_data()
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def get_cache_data(self):
    cache_dict = self.__dict__.copy()
    if hasattr(self, TYPE_ID_KEY):
        cache_dict[TYPE_ID_KEY] = getattr(self, TYPE_ID_KEY)
    return cache_dict
load_cache_data(cache_dict)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def load_cache_data(self, cache_dict):
    for k, v in cache_dict.items():
        self.__dict__[k] = v

LayoutItem(name=None, directive=None)

Bases: CachableComponent

Layout item.

Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def __init__(self, name=None, directive=None):
    self.name = name
    self.directive = directive

Attributes

type_id = None class-attribute instance-attribute
name = name instance-attribute
directive = directive instance-attribute

Functions

get_cache_data()
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def get_cache_data(self):
    cache_dict = self.__dict__.copy()
    if hasattr(self, TYPE_ID_KEY):
        cache_dict[TYPE_ID_KEY] = getattr(self, TYPE_ID_KEY)
    return cache_dict
load_cache_data(cache_dict)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def load_cache_data(self, cache_dict):
    for k, v in cache_dict.items():
        self.__dict__[k] = v

GenericComponent()

Bases: CachableComponent

Generic component object.

Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def __init__(self):
    self.name = None

Attributes

type_id = None class-attribute instance-attribute
name = None instance-attribute
is_container property

Functions

get_cache_data()
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def get_cache_data(self):
    cache_dict = self.__dict__.copy()
    if hasattr(self, TYPE_ID_KEY):
        cache_dict[TYPE_ID_KEY] = getattr(self, TYPE_ID_KEY)
    return cache_dict
load_cache_data(cache_dict)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def load_cache_data(self, cache_dict):
    for k, v in cache_dict.items():
        self.__dict__[k] = v

GenericUIComponent(cmp_path=None)

Bases: GenericComponent

Generic UI component.

Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def __init__(self, cmp_path=None):
    # using classname otherwise exceptions in superclasses won't show
    GenericComponent.__init__(self)
    self.directory = cmp_path
    self.unique_name = self.parent_ctrl_id = None
    self.icon_file = None
    self._ui_title = None
    self._tooltip = self.author = self._help_url = None
    self.media_file = None
    self.min_revit_ver = self.max_revit_ver = None
    self.is_beta = False
    self.highlight_type = None
    self.collapsed = False
    self.version = None

    self.meta = {}
    self.meta_file = None

    self.modules = []
    self.module_paths = []

    self.binary_path = None
    self.library_path = None

    if self.directory:
        self._update_from_directory()

Attributes

type_id = None class-attribute instance-attribute
name = None instance-attribute
is_container property
directory = cmp_path instance-attribute
unique_name = None instance-attribute
parent_ctrl_id = None instance-attribute
icon_file = None instance-attribute
author = None instance-attribute
media_file = None instance-attribute
min_revit_ver = None instance-attribute
max_revit_ver = None instance-attribute
is_beta = False instance-attribute
highlight_type = None instance-attribute
collapsed = False instance-attribute
version = None instance-attribute
meta = {} instance-attribute
meta_file = None instance-attribute
modules = [] instance-attribute
module_paths = [] instance-attribute
binary_path = None instance-attribute
library_path = None instance-attribute
control_id property
ui_title property
tooltip property
help_url property
is_supported property

Functions

get_cache_data()
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def get_cache_data(self):
    cache_dict = self.__dict__.copy()
    if hasattr(self, TYPE_ID_KEY):
        cache_dict[TYPE_ID_KEY] = getattr(self, TYPE_ID_KEY)
    return cache_dict
load_cache_data(cache_dict)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def load_cache_data(self, cache_dict):
    for k, v in cache_dict.items():
        self.__dict__[k] = v
matches(component_path) classmethod
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
@classmethod
def matches(cls, component_path):
    return component_path.lower().endswith(cls.type_id)
make_unique_name(cmp_path) classmethod

Creates a unique name for the command.

This is used to uniquely identify this command and also to create the class in pyRevit dll assembly. Current method create a unique name based on the command full directory address.

Examples:

for 'pyRevit.extension/pyRevit.tab/Edit.panel/Flip doors.pushbutton' unique name would be: 'pyrevit-pyrevit-edit-flipdoors'.

Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
@classmethod
def make_unique_name(cls, cmp_path):
    """Creates a unique name for the command.

    This is used to uniquely identify this command
    and also to create the class in pyRevit dll assembly.
    Current method create a unique name based on the command
    full directory address.

    Examples:
        for 'pyRevit.extension/pyRevit.tab/Edit.panel/Flip doors.pushbutton'
        unique name would be: 'pyrevit-pyrevit-edit-flipdoors'.
    """
    pieces = []
    inside_ext = False
    for dname in cmp_path.split(op.sep):
        if exts.ExtensionTypes.UI_EXTENSION.POSTFIX in dname:
            inside_ext = True

        name, ext = op.splitext(dname)
        if ext != '' and inside_ext:
            pieces.append(name)
        else:
            continue
    return coreutils.cleanup_string(
        exts.UNIQUE_ID_SEPARATOR.join(pieces),
        skip=[exts.UNIQUE_ID_SEPARATOR]
        ).lower()
get_full_bundle_name()
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def get_full_bundle_name(self):
    return self.name + self.type_id
has_module_path(path)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def has_module_path(self, path):
    return path in self.module_paths
add_module_path(path)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def add_module_path(self, path):
    if path and not self.has_module_path(path):
        mlogger.debug('Appending syspath: %s to %s', path, self)
        self.module_paths.append(path)
remove_module_path(path)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def remove_module_path(self, path):
    if path and self.has_module_path(path):
        mlogger.debug('Removing syspath: %s from %s', path, self)
        return self.module_paths.remove(path)
get_bundle_file(file_name)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def get_bundle_file(self, file_name):
    if self.directory and file_name:
        file_addr = op.join(self.directory, file_name)
        return file_addr if op.exists(file_addr) else None
find_bundle_file(patterns, finder='postfix')
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def find_bundle_file(self, patterns, finder='postfix'):
    if self.directory:
        for bundle_file in os.listdir(self.directory):
            if 'name' == finder:
                for file_name in patterns:
                    if op.splitext(bundle_file)[0] == file_name:
                        return op.join(self.directory, bundle_file)
            elif 'postfix' == finder:
                for file_postfix in patterns:
                    if bundle_file.endswith(file_postfix):
                        return op.join(self.directory, bundle_file)
            elif 'regex' == finder:
                for regex_pattern in patterns:
                    if re.match(regex_pattern, bundle_file):
                        return op.join(self.directory, bundle_file)
    return None
find_bundle_module(module, by_host=False)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def find_bundle_module(self, module, by_host=False):
    # test of file_name is an actually path to a file
    if op.isfile(module):
        return module

    def build_assm_filename(module_filename):
        # build assembly by host version (assm_file_2020.ext)
        assm_name, assm_ext = op.splitext(module_filename)
        return assm_name + '_' + HOST_APP.version + assm_ext

    if by_host:
        module = build_assm_filename(module)

    # test if module is inside search paths
    for module_path in self.module_paths:
        possible_module_path = op.join(module_path, module)
        if op.isfile(possible_module_path):
            return possible_module_path
configure(config_dict)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def configure(self, config_dict):
    configurable_params = \
        ['_ui_title', '_tooltip', '_help_url', 'author']
    # get root key:value pairs
    for key, value in config_dict.items():
        for param_name in configurable_params:
            self._resolve_liquid_tag(param_name, key, value)
    # get key:value pairs grouped under special key, if exists
    templates = config_dict.get(exts.MDATA_TEMPLATES_KEY, {})
    for key, value in templates.items():
        for param_name in configurable_params:
            self._resolve_liquid_tag(param_name, key, value)

GenericUIContainer(cmp_path=None)

Bases: GenericUIComponent

Superclass for all UI group items (tab, panel, button groups, stacks).

Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def __init__(self, cmp_path=None):
    self.layout_items = []
    self.components = []
    # using classname otherwise exceptions in superclasses won't show
    GenericUIComponent.__init__(self, cmp_path=cmp_path)

Attributes

type_id = None class-attribute instance-attribute
name = None instance-attribute
is_container property
directory = cmp_path instance-attribute
unique_name = None instance-attribute
parent_ctrl_id = None instance-attribute
icon_file = None instance-attribute
author = None instance-attribute
media_file = None instance-attribute
min_revit_ver = None instance-attribute
max_revit_ver = None instance-attribute
is_beta = False instance-attribute
highlight_type = None instance-attribute
collapsed = False instance-attribute
version = None instance-attribute
meta = {} instance-attribute
meta_file = None instance-attribute
modules = [] instance-attribute
module_paths = [] instance-attribute
binary_path = None instance-attribute
library_path = None instance-attribute
control_id property
ui_title property
tooltip property
help_url property
is_supported property
allowed_sub_cmps = [] class-attribute instance-attribute
layout_items = [] instance-attribute
components = [] instance-attribute

Functions

get_cache_data()
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def get_cache_data(self):
    cache_dict = self.__dict__.copy()
    if hasattr(self, TYPE_ID_KEY):
        cache_dict[TYPE_ID_KEY] = getattr(self, TYPE_ID_KEY)
    return cache_dict
load_cache_data(cache_dict)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def load_cache_data(self, cache_dict):
    for k, v in cache_dict.items():
        self.__dict__[k] = v
matches(component_path) classmethod
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
@classmethod
def matches(cls, component_path):
    return component_path.lower().endswith(cls.type_id)
make_unique_name(cmp_path) classmethod

Creates a unique name for the command.

This is used to uniquely identify this command and also to create the class in pyRevit dll assembly. Current method create a unique name based on the command full directory address.

Examples:

for 'pyRevit.extension/pyRevit.tab/Edit.panel/Flip doors.pushbutton' unique name would be: 'pyrevit-pyrevit-edit-flipdoors'.

Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
@classmethod
def make_unique_name(cls, cmp_path):
    """Creates a unique name for the command.

    This is used to uniquely identify this command
    and also to create the class in pyRevit dll assembly.
    Current method create a unique name based on the command
    full directory address.

    Examples:
        for 'pyRevit.extension/pyRevit.tab/Edit.panel/Flip doors.pushbutton'
        unique name would be: 'pyrevit-pyrevit-edit-flipdoors'.
    """
    pieces = []
    inside_ext = False
    for dname in cmp_path.split(op.sep):
        if exts.ExtensionTypes.UI_EXTENSION.POSTFIX in dname:
            inside_ext = True

        name, ext = op.splitext(dname)
        if ext != '' and inside_ext:
            pieces.append(name)
        else:
            continue
    return coreutils.cleanup_string(
        exts.UNIQUE_ID_SEPARATOR.join(pieces),
        skip=[exts.UNIQUE_ID_SEPARATOR]
        ).lower()
get_full_bundle_name()
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def get_full_bundle_name(self):
    return self.name + self.type_id
has_module_path(path)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def has_module_path(self, path):
    return path in self.module_paths
get_bundle_file(file_name)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def get_bundle_file(self, file_name):
    if self.directory and file_name:
        file_addr = op.join(self.directory, file_name)
        return file_addr if op.exists(file_addr) else None
find_bundle_file(patterns, finder='postfix')
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def find_bundle_file(self, patterns, finder='postfix'):
    if self.directory:
        for bundle_file in os.listdir(self.directory):
            if 'name' == finder:
                for file_name in patterns:
                    if op.splitext(bundle_file)[0] == file_name:
                        return op.join(self.directory, bundle_file)
            elif 'postfix' == finder:
                for file_postfix in patterns:
                    if bundle_file.endswith(file_postfix):
                        return op.join(self.directory, bundle_file)
            elif 'regex' == finder:
                for regex_pattern in patterns:
                    if re.match(regex_pattern, bundle_file):
                        return op.join(self.directory, bundle_file)
    return None
find_bundle_module(module, by_host=False)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def find_bundle_module(self, module, by_host=False):
    # test of file_name is an actually path to a file
    if op.isfile(module):
        return module

    def build_assm_filename(module_filename):
        # build assembly by host version (assm_file_2020.ext)
        assm_name, assm_ext = op.splitext(module_filename)
        return assm_name + '_' + HOST_APP.version + assm_ext

    if by_host:
        module = build_assm_filename(module)

    # test if module is inside search paths
    for module_path in self.module_paths:
        possible_module_path = op.join(module_path, module)
        if op.isfile(possible_module_path):
            return possible_module_path
parse_layout_directive(layout_line)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def parse_layout_directive(self, layout_line):
    parts = re.findall(r'(.+)\[(.+):(.*)\]', layout_line)
    if parts:
        source_item, directive, target_value = parts[0]
        # cleanup values
        directive = directive.lower().strip()
        target_value = target_value.strip()
        # process any escape characters in target value
        # https://stackoverflow.com/a/4020824/2350244
        target_value = target_value.encode('utf-8')
        if PY3:
            target_value = target_value.decode('unicode_escape')
        else:
            target_value = target_value.decode('string_escape')
        # create directive obj
        return source_item, LayoutDirective(directive_type=directive,
                                            target=target_value)
    return layout_line, None
parse_layout_item(layout_line)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def parse_layout_item(self, layout_line):
    if layout_line:
        layout_item_name, layout_item_drctv = \
            self.parse_layout_directive(layout_line)
        return LayoutItem(name=layout_item_name,
                          directive=layout_item_drctv)
parse_layout_items(layout_lines)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def parse_layout_items(self, layout_lines):
    for layout_line in layout_lines:
        layout_item = self.parse_layout_item(layout_line)
        if layout_item:
            self.layout_items.append(layout_item)
    mlogger.debug('Layout is: %s', self.layout_items)
parse_layout_metadata()
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def parse_layout_metadata(self):
    layout = self.meta.get(exts.MDATA_LAYOUT, [])
    if layout:
        self.parse_layout_items(layout)
        return True
contains(item_name)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def contains(self, item_name):
    return any([x.name == item_name for x in self.components])
add_module_path(path)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def add_module_path(self, path):
    if path and not self.has_module_path(path):
        mlogger.debug('Appending syspath: %s to %s', path, self)
        for component in self.components:
            component.add_module_path(path)
        self.module_paths.append(path)
remove_module_path(path)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def remove_module_path(self, path):
    if path and self.has_module_path(path):
        mlogger.debug('Removing syspath: %s from %s', path, self)
        for component in self.components:
            component.remove_module_path(path)
        return self.module_paths.remove(path)
add_component(comp)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def add_component(self, comp):
    # set search paths
    for path in self.module_paths:
        comp.add_module_path(path)
    # set its own control id on the child component
    if hasattr(comp, 'parent_ctrl_id'):
        comp.parent_ctrl_id = self.control_id
    # now add to list
    self.components.append(comp)
find_components_of_type(cmp_type)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def find_components_of_type(self, cmp_type):
    sub_comp_list = []
    for sub_comp in self.components:
        if isinstance(sub_comp, cmp_type):
            sub_comp_list.append(sub_comp)
        elif sub_comp.is_container:
            sub_comp_list.extend(sub_comp.find_components_of_type(cmp_type))

    return sub_comp_list
find_layout_items()
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def find_layout_items(self):
    layout_items = []
    layout_items.extend(self.layout_items)
    for sub_comp in self.components:
        if sub_comp.is_container:
            layout_items.extend(sub_comp.find_layout_items())
    return layout_items
configure(config_dict)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def configure(self, config_dict):
    # update self meta
    GenericUIComponent.configure(self, config_dict=config_dict)
    # create an updated dict to pass to children
    updated_dict = copy.deepcopy(config_dict)
    updated_dict = pyutils.merge(updated_dict, self.meta)
    # replace the meta values with the expanded values
    # so children can use the expanded
    updated_dict[exts.MDATA_UI_TITLE] = self.ui_title
    updated_dict[exts.MDATA_TOOLTIP] = self.tooltip
    updated_dict[exts.MDATA_COMMAND_HELP_URL] = self.help_url
    updated_dict[exts.AUTHOR_PARAM] = self.author
    if exts.AUTHORS_PARAM in updated_dict:
        updated_dict.pop(exts.AUTHORS_PARAM)
    for component in self:
        component.configure(updated_dict)

GenericUICommand(cmp_path=None, needs_script=True)

Bases: GenericUIComponent

Superclass for all single commands.

The information provided by these classes will be used to create a push button under Revit UI. However, pyRevit expands the capabilities of push button beyond what is provided by Revit UI. (e.g. Toggle button changes it's icon based on its on/off status) See LinkButton and ToggleButton classes.

Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def __init__(self, cmp_path=None, needs_script=True):
    self.needs_script = needs_script
    self.script_file = self.config_script_file = None
    self.arguments = []
    self.context = None
    self.class_name = self.avail_class_name = None
    self.requires_clean_engine = False
    self.requires_fullframe_engine = False
    self.requires_persistent_engine = False
    self.requires_mainthread_engine = False
    # engine options specific to dynamo
    self.dynamo_path = None
    # self.dynamo_path_exec = False
    self.dynamo_path_check_existing = False
    self.dynamo_force_manual_run = False
    self.dynamo_model_nodes_info = None
    # using classname otherwise exceptions in superclasses won't show
    GenericUIComponent.__init__(self, cmp_path=cmp_path)

    mlogger.debug('Maximum host version: %s', self.max_revit_ver)
    mlogger.debug('Minimum host version: %s', self.min_revit_ver)
    mlogger.debug('command tooltip: %s', self._tooltip)
    mlogger.debug('Command author: %s', self.author)
    mlogger.debug('Command help url: %s', self._help_url)

    if self.is_beta:
        mlogger.debug('Command is in beta.')

Attributes

type_id = None class-attribute instance-attribute
name = None instance-attribute
is_container property
directory = cmp_path instance-attribute
unique_name = None instance-attribute
parent_ctrl_id = None instance-attribute
icon_file = None instance-attribute
author = None instance-attribute
media_file = None instance-attribute
min_revit_ver = None instance-attribute
max_revit_ver = None instance-attribute
is_beta = False instance-attribute
highlight_type = None instance-attribute
collapsed = False instance-attribute
version = None instance-attribute
meta = {} instance-attribute
meta_file = None instance-attribute
modules = [] instance-attribute
module_paths = [] instance-attribute
binary_path = None instance-attribute
library_path = None instance-attribute
ui_title property
tooltip property
help_url property
is_supported property
needs_script = needs_script instance-attribute
script_file = None instance-attribute
config_script_file = None instance-attribute
arguments = [] instance-attribute
context = None instance-attribute
class_name = None instance-attribute
avail_class_name = None instance-attribute
requires_clean_engine = False instance-attribute
requires_fullframe_engine = False instance-attribute
requires_persistent_engine = False instance-attribute
requires_mainthread_engine = False instance-attribute
dynamo_path = None instance-attribute
dynamo_path_check_existing = False instance-attribute
dynamo_force_manual_run = False instance-attribute
dynamo_model_nodes_info = None instance-attribute
script_language property
control_id property
is_cpython property

Functions

get_cache_data()
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def get_cache_data(self):
    cache_dict = self.__dict__.copy()
    if hasattr(self, TYPE_ID_KEY):
        cache_dict[TYPE_ID_KEY] = getattr(self, TYPE_ID_KEY)
    return cache_dict
load_cache_data(cache_dict)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def load_cache_data(self, cache_dict):
    for k, v in cache_dict.items():
        self.__dict__[k] = v
matches(component_path) classmethod
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
@classmethod
def matches(cls, component_path):
    return component_path.lower().endswith(cls.type_id)
make_unique_name(cmp_path) classmethod

Creates a unique name for the command.

This is used to uniquely identify this command and also to create the class in pyRevit dll assembly. Current method create a unique name based on the command full directory address.

Examples:

for 'pyRevit.extension/pyRevit.tab/Edit.panel/Flip doors.pushbutton' unique name would be: 'pyrevit-pyrevit-edit-flipdoors'.

Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
@classmethod
def make_unique_name(cls, cmp_path):
    """Creates a unique name for the command.

    This is used to uniquely identify this command
    and also to create the class in pyRevit dll assembly.
    Current method create a unique name based on the command
    full directory address.

    Examples:
        for 'pyRevit.extension/pyRevit.tab/Edit.panel/Flip doors.pushbutton'
        unique name would be: 'pyrevit-pyrevit-edit-flipdoors'.
    """
    pieces = []
    inside_ext = False
    for dname in cmp_path.split(op.sep):
        if exts.ExtensionTypes.UI_EXTENSION.POSTFIX in dname:
            inside_ext = True

        name, ext = op.splitext(dname)
        if ext != '' and inside_ext:
            pieces.append(name)
        else:
            continue
    return coreutils.cleanup_string(
        exts.UNIQUE_ID_SEPARATOR.join(pieces),
        skip=[exts.UNIQUE_ID_SEPARATOR]
        ).lower()
get_full_bundle_name()
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def get_full_bundle_name(self):
    return self.name + self.type_id
has_module_path(path)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def has_module_path(self, path):
    return path in self.module_paths
add_module_path(path)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def add_module_path(self, path):
    if path and not self.has_module_path(path):
        mlogger.debug('Appending syspath: %s to %s', path, self)
        self.module_paths.append(path)
remove_module_path(path)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def remove_module_path(self, path):
    if path and self.has_module_path(path):
        mlogger.debug('Removing syspath: %s from %s', path, self)
        return self.module_paths.remove(path)
get_bundle_file(file_name)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def get_bundle_file(self, file_name):
    if self.directory and file_name:
        file_addr = op.join(self.directory, file_name)
        return file_addr if op.exists(file_addr) else None
find_bundle_file(patterns, finder='postfix')
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def find_bundle_file(self, patterns, finder='postfix'):
    if self.directory:
        for bundle_file in os.listdir(self.directory):
            if 'name' == finder:
                for file_name in patterns:
                    if op.splitext(bundle_file)[0] == file_name:
                        return op.join(self.directory, bundle_file)
            elif 'postfix' == finder:
                for file_postfix in patterns:
                    if bundle_file.endswith(file_postfix):
                        return op.join(self.directory, bundle_file)
            elif 'regex' == finder:
                for regex_pattern in patterns:
                    if re.match(regex_pattern, bundle_file):
                        return op.join(self.directory, bundle_file)
    return None
find_bundle_module(module, by_host=False)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def find_bundle_module(self, module, by_host=False):
    # test of file_name is an actually path to a file
    if op.isfile(module):
        return module

    def build_assm_filename(module_filename):
        # build assembly by host version (assm_file_2020.ext)
        assm_name, assm_ext = op.splitext(module_filename)
        return assm_name + '_' + HOST_APP.version + assm_ext

    if by_host:
        module = build_assm_filename(module)

    # test if module is inside search paths
    for module_path in self.module_paths:
        possible_module_path = op.join(module_path, module)
        if op.isfile(possible_module_path):
            return possible_module_path
configure(config_dict)
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def configure(self, config_dict):
    configurable_params = \
        ['_ui_title', '_tooltip', '_help_url', 'author']
    # get root key:value pairs
    for key, value in config_dict.items():
        for param_name in configurable_params:
            self._resolve_liquid_tag(param_name, key, value)
    # get key:value pairs grouped under special key, if exists
    templates = config_dict.get(exts.MDATA_TEMPLATES_KEY, {})
    for key, value in templates.items():
        for param_name in configurable_params:
            self._resolve_liquid_tag(param_name, key, value)
has_config_script()
Source code in pyrevitlib/pyrevit/extensions/genericcomps.py
def has_config_script(self):
    return self.config_script_file != self.script_file