Skip to content

runtime

Module that compiles the base DLL on load.

Attributes

mlogger = logger.get_logger(__name__) module-attribute

INTERFACE_TYPES_DIR = RUNTIME_DIR module-attribute

DOTNET_DIR = op.join(os.getenv('windir'), 'Microsoft.NET', 'Framework') module-attribute

DOTNET64_DIR = op.join(os.getenv('windir'), 'Microsoft.NET', 'Framework64') module-attribute

DOTNET_SDK_DIR = op.join(os.getenv('programfiles(x86)'), 'Reference Assemblies', 'Microsoft', 'Framework', '.NETFramework') module-attribute

DOTNET_FRAMEWORK_DIRS = sorted([x for x in os.listdir(DOTNET_DIR) if x.startswith('v4.') and 'X' not in x], reverse=True) module-attribute

DOTNET64_FRAMEWORK_DIRS = sorted([x for x in os.listdir(DOTNET64_DIR) if x.startswith('v4.') and 'X' not in x], reverse=True) module-attribute

DOTNET_TARGETPACK_DIRS = sorted([x for x in os.listdir(DOTNET_SDK_DIR) if x.startswith('v4.') and 'X' not in x], reverse=True) module-attribute

RUNTIME_NAMESPACE = 'PyRevitLabs.PyRevit.Runtime' module-attribute

CMD_EXECUTOR_TYPE_NAME = '{}.{}'.format(RUNTIME_NAMESPACE, 'ScriptCommand') module-attribute

CMD_AVAIL_TYPE_NAME_EXTENDED = coreutils.make_canonical_name(RUNTIME_NAMESPACE, 'ScriptCommandExtendedAvail') module-attribute

CMD_AVAIL_TYPE_NAME_SELECTION = coreutils.make_canonical_name(RUNTIME_NAMESPACE, 'ScriptCommandSelectionAvail') module-attribute

CMD_AVAIL_TYPE_NAME_ZERODOC = coreutils.make_canonical_name(RUNTIME_NAMESPACE, 'ScriptCommandZeroDocAvail') module-attribute

CMD_AVAIL_NAME_POSTFIX = '-avail' module-attribute

SOURCE_FILE_EXT = '.cs' module-attribute

SOURCE_FILE_FILTER = '(\\.cs)' module-attribute

CPYTHON_ENGINE = user_config.get_active_cpython_engine() module-attribute

BASE_TYPES_DIR_HASH = coreutils.get_str_hash(coreutils.calculate_dir_hash(INTERFACE_TYPES_DIR, '', SOURCE_FILE_FILTER) + EXEC_PARAMS.engine_ver + str(CPYTHON_ENGINE.Version) if CPYTHON_ENGINE else '0')[:HASH_CUTOFF_LENGTH] module-attribute

RUNTIME_ASSM_FILE_ID = '{}_{}'.format(BASE_TYPES_DIR_HASH, RUNTIME_NAMESPACE) module-attribute

RUNTIME_ASSM_FILE = op.join(BIN_DIR, 'pyRevitLabs.PyRevit.Runtime.{}.dll'.format(HOST_APP.version)) module-attribute

RUNTIME_ASSM_NAME = op.splitext(op.basename(RUNTIME_ASSM_FILE))[0] module-attribute

RUNTIME_ASSM = None module-attribute

assm_list = assmutils.find_loaded_asm(RUNTIME_ASSM_NAME) module-attribute

CMD_EXECUTOR_TYPE = assmutils.find_type_by_name(RUNTIME_ASSM, CMD_EXECUTOR_TYPE_NAME) module-attribute

CMD_AVAIL_TYPE_EXTENDED = assmutils.find_type_by_name(RUNTIME_ASSM, CMD_AVAIL_TYPE_NAME_EXTENDED) module-attribute

CMD_AVAIL_TYPE_SELECTION = assmutils.find_type_by_name(RUNTIME_ASSM, CMD_AVAIL_TYPE_NAME_SELECTION) module-attribute

CMD_AVAIL_TYPE_ZERODOC = assmutils.find_type_by_name(RUNTIME_ASSM, CMD_AVAIL_TYPE_NAME_ZERODOC) module-attribute

Classes

Functions

get_references()

Get list of all referenced assemblies.

Returns:

Type Description
list

referenced assemblies

Source code in pyrevitlib/pyrevit/runtime/__init__.py
def get_references():
    """Get list of all referenced assemblies.

    Returns:
        (list): referenced assemblies
    """
    ref_list = [
        # system stuff
        'System', 'System.Core', 'System.Runtime', 'System.Linq', 'System.Collections',
        'System.Collections.Immutable', 'System.Console',
        'System.Xaml', 'System.Web', 'System.Xml', 'System.Numerics',
        'System.Drawing', 'System.Drawing', 'System.Windows.Forms',
        'System.ComponentModel.Primitives', 'System.ComponentModel.TypeConverter',
        'PresentationCore', 'PresentationFramework',
        'WindowsBase', 'WindowsFormsIntegration',
        # legacy csharp/vb.net compiler
        'Microsoft.CSharp',
        # iron python engine
        '{prefix}Microsoft.Dynamic'.format(prefix=eng.EnginePrefix),
        '{prefix}Microsoft.Scripting'.format(prefix=eng.EnginePrefix),
        '{prefix}IronPython'.format(prefix=eng.EnginePrefix),
        '{prefix}IronPython.Modules'.format(prefix=eng.EnginePrefix),
        # revit api
        'RevitAPI', 'RevitAPIUI', 'AdWindows', 'UIFramework',
        # pyrevit loader assembly
        'pyRevitLoader',
        # pyrevit labs
        'pyRevitLabs.Common', 'pyRevitLabs.CommonWPF',
        'pyRevitLabs.MahAppsMetro',
        'pyRevitLabs.NLog',
        'pyRevitLabs.Json',
        'pyRevitLabs.Emojis',
        'pyRevitLabs.TargetApps.Revit',
        'pyRevitLabs.PyRevit',
        'pyRevitLabs.PyRevit.Runtime.Shared',
    ]

    # netcore depends
    if compat.NETCORE:
        ref_list.extend(['System.Drawing.Common',
                         'System.Diagnostics.Process',
                         'System.Diagnostics.FileVersionInfo',
                         'System.Text.RegularExpressions'])

    # another revit api
    if HOST_APP.is_newer_than(2018):
        ref_list.extend(['Xceed.Wpf.AvalonDock'])

    refs = (_get_reference_file(ref_name) for ref_name in ref_list)
    return [r for r in refs if r]

create_ipyengine_configs(clean=False, full_frame=False, persistent=False)

Return the configuration for ipython engine.

Parameters:

Name Type Description Default
clean bool

Engine should be clean. Defaults to False.

False
full_frame bool

Engine shoul be full frame. Defaults to False.

False
persistent bool

Engine should persist. Defaults to False.

False

Returns:

Type Description
str

Configuration

Source code in pyrevitlib/pyrevit/runtime/__init__.py
def create_ipyengine_configs(clean=False, full_frame=False, persistent=False):
    """Return the configuration for ipython engine.

    Args:
        clean (bool, optional): Engine should be clean. Defaults to False.
        full_frame (bool, optional): Engine shoul be full frame. Defaults to False.
        persistent (bool, optional): Engine should persist. Defaults to False.

    Returns:
        (str): Configuration
    """
    return json.dumps({
        exts.MDATA_ENGINE_CLEAN: clean,
        exts.MDATA_ENGINE_FULLFRAME: full_frame,
        exts.MDATA_ENGINE_PERSISTENT: persistent,
    })

create_ext_command_attrs()

Create dotnet attributes for Revit external commands.

This method is used in creating custom dotnet types for pyRevit commands and compiling them into a DLL assembly. Current implementation sets RegenerationOption.Manual and TransactionMode.Manual

Returns:

Type Description
list[CustomAttributeBuilder]

object for RegenerationOption and TransactionMode attributes.

Source code in pyrevitlib/pyrevit/runtime/__init__.py
def create_ext_command_attrs():
    """Create dotnet attributes for Revit external commands.

    This method is used in creating custom dotnet types for pyRevit commands
    and compiling them into a DLL assembly. Current implementation sets
    ``RegenerationOption.Manual`` and ``TransactionMode.Manual``

    Returns:
        (list[CustomAttributeBuilder]): object for `RegenerationOption` 
            and `TransactionMode` attributes.
    """
    regen_const_info = \
        framework.clr.GetClrType(api.Attributes.RegenerationAttribute) \
        .GetConstructor(
            framework.Array[framework.Type](
                (api.Attributes.RegenerationOption,)
                ))

    regen_attr_builder = \
        framework.CustomAttributeBuilder(
            regen_const_info,
            framework.Array[object](
                (api.Attributes.RegenerationOption.Manual,)
                ))

    # add TransactionAttribute to framework.Type
    trans_constructor_info = \
        framework.clr.GetClrType(api.Attributes.TransactionAttribute) \
        .GetConstructor(
            framework.Array[framework.Type](
                (api.Attributes.TransactionMode,)
                )
            )

    trans_attrib_builder = \
        framework.CustomAttributeBuilder(
            trans_constructor_info,
            framework.Array[object](
                (api.Attributes.TransactionMode.Manual,)
                )
            )

    return [regen_attr_builder, trans_attrib_builder]

create_type(modulebuilder, type_class, class_name, custom_attr_list, *args)

Create a dotnet type for a pyRevit command.

See baseclasses.cs code for the template pyRevit command dotnet type and its constructor default arguments that must be provided here.

Parameters:

Name Type Description Default
modulebuilder

obj:ModuleBuilder): dotnet module builder

required
type_class type

source dotnet type for the command

required
class_name str

name for the new type

required
custom_attr_list

obj:list): list of dotnet attributes for the type

required
*args Any

list of arguments to be used with type constructor

()

Returns:

Type Description
type

returns created dotnet type

Examples:

asm_builder = AppDomain.CurrentDomain.DefineDynamicAssembly(
win_asm_name, AssemblyBuilderAccess.RunAndSave, filepath
)
module_builder = asm_builder.DefineDynamicModule(
ext_asm_file_name, ext_asm_full_file_name
)
create_type(
    module_builder,
    runtime.ScriptCommand,
    "PyRevitSomeCommandUniqueName",
    runtime.create_ext_command_attrs(),
    [scriptpath, atlscriptpath, searchpath, helpurl, name,
    bundle, extension, uniquename, False, False])

Source code in pyrevitlib/pyrevit/runtime/__init__.py
def create_type(modulebuilder, type_class, class_name, custom_attr_list, *args):
    """Create a dotnet type for a pyRevit command.

    See ``baseclasses.cs`` code for the template pyRevit command dotnet type
    and its constructor default arguments that must be provided here.

    Args:
        modulebuilder (:obj:`ModuleBuilder`): dotnet module builder
        type_class (type): source dotnet type for the command
        class_name (str): name for the new type
        custom_attr_list (:obj:`list`): list of dotnet attributes for the type
        *args (Any): list of arguments to be used with type constructor

    Returns:
        (type): returns created dotnet type

    Examples:
        ```python
        asm_builder = AppDomain.CurrentDomain.DefineDynamicAssembly(
        win_asm_name, AssemblyBuilderAccess.RunAndSave, filepath
        )
        module_builder = asm_builder.DefineDynamicModule(
        ext_asm_file_name, ext_asm_full_file_name
        )
        create_type(
            module_builder,
            runtime.ScriptCommand,
            "PyRevitSomeCommandUniqueName",
            runtime.create_ext_command_attrs(),
            [scriptpath, atlscriptpath, searchpath, helpurl, name,
            bundle, extension, uniquename, False, False])
        ```
        <type PyRevitSomeCommandUniqueName>
    """
    # create type builder
    type_builder = \
        modulebuilder.DefineType(
            class_name,
            framework.TypeAttributes.Class | framework.TypeAttributes.Public,
            type_class
            )

    for custom_attr in custom_attr_list:
        type_builder.SetCustomAttribute(custom_attr)

    # prepare a list of input param types to find the matching constructor
    type_list = []
    param_list = []
    for param in args:
        if isinstance(param, str) \
                or isinstance(param, int):
            type_list.append(type(param))
            param_list.append(param)

    # call base constructor
    constructor = \
        type_class.GetConstructor(framework.Array[framework.Type](type_list))
    # create class constructor builder
    const_builder = \
        type_builder.DefineConstructor(framework.MethodAttributes.Public,
                                       framework.CallingConventions.Standard,
                                       framework.Array[framework.Type](()))
    # add constructor parameters to stack
    gen = const_builder.GetILGenerator()
    gen.Emit(framework.OpCodes.Ldarg_0)  # Load "this" onto eval stack

    # add constructor input params to the stack
    for param_type, param in zip(type_list, param_list):
        if param_type == str:
            gen.Emit(framework.OpCodes.Ldstr, param)
        elif param_type == int:
            gen.Emit(framework.OpCodes.Ldc_I4, param)

    # call base constructor (consumes "this" and the created stack)
    gen.Emit(framework.OpCodes.Call, constructor)
    # Fill some space - this is how it is generated for equivalent C# code
    gen.Emit(framework.OpCodes.Nop)
    gen.Emit(framework.OpCodes.Nop)
    gen.Emit(framework.OpCodes.Nop)
    gen.Emit(framework.OpCodes.Ret)
    return type_builder.CreateType()