Skip to content

components

Base classes for pyRevit extension components.

Attributes

mlogger = get_logger(__name__) module-attribute

EXT_HASH_VALUE_KEY = 'dir_hash_value' module-attribute

EXT_HASH_VERSION_KEY = 'pyrvt_version' module-attribute

Classes

NoButton(cmp_path=None, needs_script=True)

Bases: GenericUICommand

This is not a button.

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

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
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
is_cpython property
type_id = exts.NOGUI_COMMAND_POSTFIX 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
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

NoScriptButton(cmp_path=None, needs_commandclass=False)

Bases: GenericUICommand

Base for buttons that doesn't run a script.

Source code in pyrevitlib/pyrevit/extensions/components.py
def __init__(self, cmp_path=None, needs_commandclass=False):
    # using classname otherwise exceptions in superclasses won't show
    GenericUICommand.__init__(self, cmp_path=cmp_path, needs_script=False)
    self.assembly = self.command_class = self.avail_command_class = None
    # read metadata from metadata file
    if self.meta:
        # get the target assembly from metadata
        self.assembly = \
            self.meta.get(exts.MDATA_LINK_BUTTON_ASSEMBLY, None)

        # get the target command class from metadata
        self.command_class = \
            self.meta.get(exts.MDATA_LINK_BUTTON_COMMAND_CLASS, None)

        # get the target command class from metadata
        self.avail_command_class = \
            self.meta.get(exts.MDATA_LINK_BUTTON_AVAIL_COMMAND_CLASS, None)

        # for invoke buttons there is no script source so
        # assign the metadata file to the script
        self.script_file = self.config_script_file = self.meta_file
    else:
        mlogger.debug("%s does not specify target assembly::class.", self)

    if self.directory and not self.assembly:
        mlogger.error("%s does not specify target assembly.", self)

    if self.directory and needs_commandclass and not self.command_class:
        mlogger.error("%s does not specify target command class.", self)

    mlogger.debug('%s assembly.class: %s.%s',
                  self, self.assembly, self.command_class)

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
needs_script = needs_script 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
is_cpython property
assembly = None instance-attribute
command_class = None instance-attribute
avail_command_class = None instance-attribute
script_file = self.meta_file instance-attribute
config_script_file = self.meta_file 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
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
get_target_assembly(required=False)
Source code in pyrevitlib/pyrevit/extensions/components.py
def get_target_assembly(self, required=False):
    assm_file = self.assembly.lower()
    if not assm_file.endswith(framework.ASSEMBLY_FILE_TYPE):
        assm_file += '.' + framework.ASSEMBLY_FILE_TYPE

    # try finding assembly for this specific host version
    target_asm_by_host = self.find_bundle_module(assm_file, by_host=True)
    if target_asm_by_host:
        return target_asm_by_host
    # try find assembly by its name
    target_asm = self.find_bundle_module(assm_file)
    if target_asm:
        return target_asm

    if required:
        mlogger.error("%s can not find target assembly.", self)

    return ''

LinkButton(cmp_path=None)

Bases: NoScriptButton

Link button.

Source code in pyrevitlib/pyrevit/extensions/components.py
def __init__(self, cmp_path=None):
    # using classname otherwise exceptions in superclasses won't show
    NoScriptButton.__init__(
        self,
        cmp_path=cmp_path,
        needs_commandclass=True
        )

    if self.context:
        mlogger.warn(
            "Linkbutton bundles do not support \"context:\". "
            "Use \"availability_class:\" instead and specify name of "
            "availability class in target assembly | %s", self
            )
        self.context = None

Attributes

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
needs_script = needs_script instance-attribute
script_file = self.meta_file instance-attribute
config_script_file = self.meta_file instance-attribute
arguments = [] 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
is_cpython property
assembly = None instance-attribute
command_class = None instance-attribute
avail_command_class = None instance-attribute
type_id = exts.LINK_BUTTON_POSTFIX class-attribute instance-attribute
context = None 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
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
get_target_assembly(required=False)
Source code in pyrevitlib/pyrevit/extensions/components.py
def get_target_assembly(self, required=False):
    assm_file = self.assembly.lower()
    if not assm_file.endswith(framework.ASSEMBLY_FILE_TYPE):
        assm_file += '.' + framework.ASSEMBLY_FILE_TYPE

    # try finding assembly for this specific host version
    target_asm_by_host = self.find_bundle_module(assm_file, by_host=True)
    if target_asm_by_host:
        return target_asm_by_host
    # try find assembly by its name
    target_asm = self.find_bundle_module(assm_file)
    if target_asm:
        return target_asm

    if required:
        mlogger.error("%s can not find target assembly.", self)

    return ''

InvokeButton(cmp_path=None)

Bases: NoScriptButton

Invoke button.

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

Attributes

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
needs_script = needs_script instance-attribute
script_file = self.meta_file instance-attribute
config_script_file = self.meta_file 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
is_cpython property
assembly = None instance-attribute
command_class = None instance-attribute
avail_command_class = None instance-attribute
type_id = exts.INVOKE_BUTTON_POSTFIX 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
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
get_target_assembly(required=False)
Source code in pyrevitlib/pyrevit/extensions/components.py
def get_target_assembly(self, required=False):
    assm_file = self.assembly.lower()
    if not assm_file.endswith(framework.ASSEMBLY_FILE_TYPE):
        assm_file += '.' + framework.ASSEMBLY_FILE_TYPE

    # try finding assembly for this specific host version
    target_asm_by_host = self.find_bundle_module(assm_file, by_host=True)
    if target_asm_by_host:
        return target_asm_by_host
    # try find assembly by its name
    target_asm = self.find_bundle_module(assm_file)
    if target_asm:
        return target_asm

    if required:
        mlogger.error("%s can not find target assembly.", self)

    return ''

PushButton(cmp_path=None, needs_script=True)

Bases: GenericUICommand

Push button.

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

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
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
is_cpython property
type_id = exts.PUSH_BUTTON_POSTFIX 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
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

PanelPushButton(cmp_path=None, needs_script=True)

Bases: GenericUICommand

Panel push button.

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

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
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
is_cpython property
type_id = exts.PANEL_PUSH_BUTTON_POSTFIX 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
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

SmartButton(cmp_path=None, needs_script=True)

Bases: GenericUICommand

Smart button.

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

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
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
is_cpython property
type_id = exts.SMART_BUTTON_POSTFIX 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
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

ContentButton(cmp_path=None)

Bases: GenericUICommand

Content Button.

Source code in pyrevitlib/pyrevit/extensions/components.py
def __init__(self, cmp_path=None):
    # using classname otherwise exceptions in superclasses won't show
    GenericUICommand.__init__(
        self,
        cmp_path=cmp_path,
        needs_script=False
        )
    # find content file
    self.script_file = \
        self.find_bundle_file([
            exts.CONTENT_VERSION_POSTFIX.format(
                version=HOST_APP.version
                ),
            ])
    if not self.script_file:
        self.script_file = \
            self.find_bundle_file([
                exts.CONTENT_POSTFIX,
                ])
    # requires at least one bundles
    if self.directory and not self.script_file:
        mlogger.error('Command %s: Does not have content file.', self)
        self.script_file = ''

    # find alternative content file
    self.config_script_file = \
        self.find_bundle_file([
            exts.ALT_CONTENT_VERSION_POSTFIX.format(
                version=HOST_APP.version
                ),
            ])
    if not self.config_script_file:
        self.config_script_file = \
            self.find_bundle_file([
                exts.ALT_CONTENT_POSTFIX,
                ])
    if not self.config_script_file:
        self.config_script_file = self.script_file

Attributes

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
needs_script = needs_script 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
is_cpython property
type_id = exts.CONTENT_BUTTON_POSTFIX class-attribute instance-attribute
script_file = self.find_bundle_file([exts.CONTENT_VERSION_POSTFIX.format(version=HOST_APP.version)]) instance-attribute
config_script_file = self.find_bundle_file([exts.ALT_CONTENT_VERSION_POSTFIX.format(version=HOST_APP.version)]) 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
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

URLButton(cmp_path=None)

Bases: GenericUICommand

URL button.

Source code in pyrevitlib/pyrevit/extensions/components.py
def __init__(self, cmp_path=None):
    # using classname otherwise exceptions in superclasses won't show
    GenericUICommand.__init__(self, cmp_path=cmp_path, needs_script=False)
    self.target_url = None
    # read metadata from metadata file
    if self.meta:
        # get the target url from metadata
        self.target_url = \
            self.meta.get(exts.MDATA_URL_BUTTON_HYPERLINK, None)
        # for url buttons there is no script source so
        # assign the metadata file to the script
        self.script_file = self.config_script_file = self.meta_file
    else:
        mlogger.debug("%s does not specify target assembly::class.", self)

    if self.directory and not self.target_url:
        mlogger.error("%s does not specify target url.", self)

    mlogger.debug('%s target url: %s', self, self.target_url)

Attributes

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
needs_script = needs_script 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
is_cpython property
type_id = exts.URL_BUTTON_POSTFIX class-attribute instance-attribute
target_url = None instance-attribute
script_file = self.meta_file instance-attribute
config_script_file = self.meta_file 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
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
get_target_url()
Source code in pyrevitlib/pyrevit/extensions/components.py
def get_target_url(self):
    return self.target_url or ""

GenericUICommandGroup(cmp_path=None)

Bases: GenericUIContainer

Generic UI command group.

Command groups only include commands. These classes can include GenericUICommand as sub components.

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
ui_title property
tooltip property
help_url property
is_supported property
layout_items = [] instance-attribute
components = [] instance-attribute
allowed_sub_cmps = [GenericUICommand, NoScriptButton] class-attribute instance-attribute
control_id 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)
        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)
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):
    # 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)
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_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
has_commands()
Source code in pyrevitlib/pyrevit/extensions/components.py
def has_commands(self):
    for component in self:
        if isinstance(component, GenericUICommand):
            return True

PullDownButtonGroup(cmp_path=None)

Bases: GenericUICommandGroup

Pulldown button group.

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

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 = [GenericUICommand, NoScriptButton] class-attribute instance-attribute
layout_items = [] instance-attribute
components = [] instance-attribute
type_id = exts.PULLDOWN_BUTTON_POSTFIX 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
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)
        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)
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):
    # 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)
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_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
has_commands()
Source code in pyrevitlib/pyrevit/extensions/components.py
def has_commands(self):
    for component in self:
        if isinstance(component, GenericUICommand):
            return True

SplitPushButtonGroup(cmp_path=None)

Bases: GenericUICommandGroup

Split push button group.

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

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 = [GenericUICommand, NoScriptButton] class-attribute instance-attribute
layout_items = [] instance-attribute
components = [] instance-attribute
type_id = exts.SPLITPUSH_BUTTON_POSTFIX 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
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)
        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)
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):
    # 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)
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_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
has_commands()
Source code in pyrevitlib/pyrevit/extensions/components.py
def has_commands(self):
    for component in self:
        if isinstance(component, GenericUICommand):
            return True

SplitButtonGroup(cmp_path=None)

Bases: GenericUICommandGroup

Split button group.

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

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 = [GenericUICommand, NoScriptButton] class-attribute instance-attribute
layout_items = [] instance-attribute
components = [] instance-attribute
type_id = exts.SPLIT_BUTTON_POSTFIX 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
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)
        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)
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):
    # 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)
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_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
has_commands()
Source code in pyrevitlib/pyrevit/extensions/components.py
def has_commands(self):
    for component in self:
        if isinstance(component, GenericUICommand):
            return True

GenericStack(cmp_path=None)

Bases: GenericUIContainer

Generic UI stack.

Stacks include GenericUICommand, or GenericUICommandGroup.

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

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
layout_items = [] instance-attribute
components = [] instance-attribute
type_id = exts.STACK_BUTTON_POSTFIX class-attribute instance-attribute
allowed_sub_cmps = [GenericUICommandGroup, GenericUICommand, NoScriptButton] class-attribute instance-attribute
control_id 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)
        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)
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):
    # 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)
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_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
has_commands()
Source code in pyrevitlib/pyrevit/extensions/components.py
def has_commands(self):
    for component in self:
        if not component.is_container:
            if isinstance(component, GenericUICommand):
                return True
        else:
            if component.has_commands():
                return True

StackButtonGroup(cmp_path=None)

Bases: GenericStack

Stack buttons group.

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

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 = [GenericUICommandGroup, GenericUICommand, NoScriptButton] class-attribute instance-attribute
layout_items = [] instance-attribute
components = [] instance-attribute
type_id = exts.STACK_BUTTON_POSTFIX 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
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)
        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)
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):
    # 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)
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_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
has_commands()
Source code in pyrevitlib/pyrevit/extensions/components.py
def has_commands(self):
    for component in self:
        if not component.is_container:
            if isinstance(component, GenericUICommand):
                return True
        else:
            if component.has_commands():
                return True

Panel(cmp_path=None)

Bases: GenericUIContainer

Panel container.

Panels include GenericStack, GenericUICommand, or GenericUICommandGroup

Source code in pyrevitlib/pyrevit/extensions/components.py
def __init__(self, cmp_path=None):
    # using classname otherwise exceptions in superclasses won't show
    GenericUIContainer.__init__(self, cmp_path=cmp_path)
    self.panel_background = \
        self.title_background = \
            self.slideout_background = None
    # read metadata from metadata file
    if self.meta:
        # check for background color configs
        self.panel_background = \
            self.meta.get(exts.MDATA_BACKGROUND_KEY, None)
        if self.panel_background:
            if isinstance(self.panel_background, dict):
                self.title_background = self.panel_background.get(
                    exts.MDATA_BACKGROUND_TITLE_KEY, None)
                self.slideout_background = self.panel_background.get(
                    exts.MDATA_BACKGROUND_SLIDEOUT_KEY, None)
                self.panel_background = self.panel_background.get(
                    exts.MDATA_BACKGROUND_PANEL_KEY, None)
            elif not isinstance(self.panel_background, str):
                mlogger.error(
                    "%s bad background definition in metadata.", self)

Attributes

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
layout_items = [] instance-attribute
components = [] instance-attribute
type_id = exts.PANEL_POSTFIX class-attribute instance-attribute
allowed_sub_cmps = [GenericStack, GenericUICommandGroup, GenericUICommand, NoScriptButton] class-attribute instance-attribute
panel_background = None instance-attribute
title_background = None instance-attribute
slideout_background = None 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
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)
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):
    # 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)
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
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
has_commands()
Source code in pyrevitlib/pyrevit/extensions/components.py
def has_commands(self):
    for component in self:
        if not component.is_container:
            if isinstance(component, GenericUICommand):
                return True
        else:
            if component.has_commands():
                return True
contains(item_name)
Source code in pyrevitlib/pyrevit/extensions/components.py
def contains(self, item_name):
    # Panels contain stacks. But stacks itself does not have any ui and its
    # subitems are displayed within the ui of the parent panel.
    # This is different from pulldowns and other button groups.
    # Button groups, contain and display their sub components in their
    # own drop down menu. So when checking if panel has a button,
    # panel should check all the items visible to the user and respond.
    item_exists = GenericUIContainer.contains(self, item_name)
    if item_exists:
        return True
    else:
        # if child is a stack item, check its children too
        for component in self:
            if isinstance(component, GenericStack) \
                    and component.contains(item_name):
                return True

Tab(cmp_path=None)

Bases: GenericUIContainer

Tab container for Panels.

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

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
layout_items = [] instance-attribute
components = [] instance-attribute
type_id = exts.TAB_POSTFIX class-attribute instance-attribute
allowed_sub_cmps = [Panel] 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
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)
        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)
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):
    # 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)
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_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
has_commands()
Source code in pyrevitlib/pyrevit/extensions/components.py
def has_commands(self):
    for panel in self:
        if panel.has_commands():
            return True
    return False

Extension(cmp_path=None)

Bases: GenericUIContainer

UI Tools extension.

Source code in pyrevitlib/pyrevit/extensions/components.py
def __init__(self, cmp_path=None):
    self.pyrvt_version = None
    self.dir_hash_value = None
    # using classname otherwise exceptions in superclasses won't show
    GenericUIContainer.__init__(self, cmp_path=cmp_path)

Attributes

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
layout_items = [] instance-attribute
components = [] instance-attribute
type_id = exts.ExtensionTypes.UI_EXTENSION.POSTFIX class-attribute instance-attribute
allowed_sub_cmps = [Tab] class-attribute instance-attribute
pyrvt_version = None instance-attribute
dir_hash_value = None instance-attribute
control_id property
startup_script 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)
        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)
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_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
get_hash()
Source code in pyrevitlib/pyrevit/extensions/components.py
def get_hash(self):
    return coreutils.get_str_hash(safe_strtype(self.get_cache_data()))
get_all_commands()
Source code in pyrevitlib/pyrevit/extensions/components.py
def get_all_commands(self):
    return self.find_components_of_type(GenericUICommand)
get_manifest_file()
Source code in pyrevitlib/pyrevit/extensions/components.py
def get_manifest_file(self):
    return self.get_bundle_file(exts.EXT_MANIFEST_FILE)
get_manifest()
Source code in pyrevitlib/pyrevit/extensions/components.py
def get_manifest(self):
    manifest_file = self.get_manifest_file()
    if manifest_file:
        with codecs.open(manifest_file, 'r', 'utf-8') as mfile:
            try:
                manifest_cfg = json.load(mfile)
                return manifest_cfg
            except Exception as manfload_err:
                print('Can not parse ext manifest file: {} '
                      '| {}'.format(manifest_file, manfload_err))
                return
configure()
Source code in pyrevitlib/pyrevit/extensions/components.py
def configure(self):
    cfg_dict = self.get_manifest()
    if cfg_dict:
        for component in self:
            component.configure(cfg_dict)
get_extension_modules()
Source code in pyrevitlib/pyrevit/extensions/components.py
def get_extension_modules(self):
    modules = []
    if self.binary_path and op.exists(self.binary_path):
        for item in os.listdir(self.binary_path):
            item_path = op.join(self.binary_path, item)
            item_name = item.lower()
            if op.isfile(item_path) \
                    and item_name.endswith(framework.ASSEMBLY_FILE_TYPE):
                modules.append(item_path)
    return modules
get_command_modules()
Source code in pyrevitlib/pyrevit/extensions/components.py
def get_command_modules(self):
    referenced_modules = set()
    for cmd in self.get_all_commands():
        for module in cmd.modules:
            cmd_module = cmd.find_bundle_module(module)
            if cmd_module:
                referenced_modules.add(cmd_module)
    return referenced_modules
get_hooks()
Source code in pyrevitlib/pyrevit/extensions/components.py
def get_hooks(self):
    hook_scripts = os.listdir(self.hooks_path) if self.hooks_path else []
    return [op.join(self.hooks_path, x) for x in hook_scripts]
get_checks()
Source code in pyrevitlib/pyrevit/extensions/components.py
def get_checks(self):
    check_scripts = os.listdir(self.checks_path) if self.checks_path else []
    return [op.join(self.checks_path, x) for x in check_scripts]

LibraryExtension(cmp_path=None)

Bases: GenericComponent

Library extension.

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

    if self.directory:
        self.name = op.splitext(op.basename(self.directory))[0]

Attributes

is_container property
type_id = exts.ExtensionTypes.LIB_EXTENSION.POSTFIX class-attribute instance-attribute
directory = cmp_path instance-attribute
name = op.splitext(op.basename(self.directory))[0] 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/components.py
@classmethod
def matches(cls, component_path):
    return component_path.lower().endswith(cls.type_id)

Functions