Core API (revitpy.api)
RevitAPI
The primary interface for interacting with Autodesk Revit.
Module: revitpy.api.wrapper
class RevitAPI:
def __init__(self, application: IRevitApplication | None = None) -> None
Properties:
| Property | Type | Description |
|---|---|---|
is_connected |
bool |
Whether the API is connected to Revit |
active_document |
RevitDocumentProvider \| None |
The currently active document provider |
elements |
ElementSet |
Access to elements in the active document |
Methods:
def connect(self) -> None
Connect to the Revit application.
def disconnect(self) -> None
Disconnect from the Revit application.
def open_document(self, file_path: str) -> RevitDocumentProvider
Open a Revit document from a file path.
def create_document(self, template_path: str | None = None) -> RevitDocumentProvider
Create a new Revit document, optionally from a template.
def get_document_info(self, provider: RevitDocumentProvider | None = None) -> DocumentInfo
Get information about a document. Uses active document if provider is not specified.
def save_document(self, provider: RevitDocumentProvider | None = None) -> None
Save a document. Uses active document if provider is not specified.
def close_document(self, provider: RevitDocumentProvider | None = None, save_changes: bool = True) -> None
Close a document. Uses active document if provider is not specified.
def query(self, element_type: str) -> "QueryBuilder"
Create a query builder for the given element type.
def transaction(self, name: str, **kwargs) -> Transaction
Create a new transaction. Can be used as a context manager.
def transaction_group(self, name: str) -> TransactionGroup
Create a new transaction group.
def get_element_by_id(self, element_id: int | ElementId) -> Element | None
Get an element by its ID.
def delete_elements(self, elements: list[Element | int | ElementId]) -> None
Delete elements from the document.
def refresh_cache(self) -> None
Refresh the internal element cache.
Element
Represents a Revit element with parameter access and change tracking.
Module: revitpy.api.element
class Element:
def __init__(self, revit_element, provider: RevitDocumentProvider | None = None) -> None
Properties:
| Property | Type | Description |
|---|---|---|
id |
ElementId |
The element’s unique identifier |
name |
str |
The element’s name |
is_dirty |
bool |
Whether the element has unsaved changes |
changes |
dict[str, Any] |
Dictionary of pending changes |
Methods:
def get_parameter_value(self, parameter_name: str, use_cache: bool = True) -> Any
Get the value of a parameter by name.
def set_parameter_value(self, parameter_name: str, value: Any, track_changes: bool = True) -> None
Set the value of a parameter.
def get_all_parameters(self, refresh_cache: bool = False) -> dict[str, Any]
Get all parameters as a dictionary.
def save_changes(self) -> None
Save all pending changes to the element.
def discard_changes(self) -> None
Discard all pending changes.
def refresh(self) -> None
Refresh element data from Revit.
ElementSet[T]
A LINQ-style collection of elements supporting fluent query operations.
Module: revitpy.api.element
Properties:
| Property | Type | Description |
|---|---|---|
count |
int |
Number of elements in the set |
Methods:
def where(self, predicate: Callable[[T], bool]) -> "ElementSet[T]"
Filter elements by a predicate function.
def select(self, selector: Callable[[T], Any]) -> "ElementSet[Any]"
Project elements using a selector function.
def first(self, predicate: Callable[[T], bool] | None = None) -> T
Return the first element, optionally matching a predicate. Raises if empty.
def first_or_default(self, predicate: Callable[[T], bool] | None = None, default: T | None = None) -> T | None
Return the first element or a default value.
def single(self, predicate: Callable[[T], bool] | None = None) -> T
Return the single matching element. Raises if zero or more than one match.
def to_list(self) -> list[T]
Convert the element set to a list.
def any(self, predicate: Callable[[T], bool] | None = None) -> bool
Check if any elements match the predicate.
def all(self, predicate: Callable[[T], bool]) -> bool
Check if all elements match the predicate.
def order_by(self, key_selector: Callable[[T], Any]) -> "ElementSet[T]"
Sort elements by a key selector.
def group_by(self, key_selector: Callable[[T], Any]) -> dict[Any, list[T]]
Group elements by a key selector.
ElementId
Module: revitpy.api.element
@dataclass
class ElementId:
value: int
ParameterValue
Module: revitpy.api.element
A Pydantic model representing a parameter value with metadata.
Transaction
Manages Revit transactions with context manager support.
Module: revitpy.api.transaction
class Transaction:
def __init__(self, provider, name: str = "Transaction", options: TransactionOptions | None = None) -> None
Properties:
| Property | Type | Description |
|---|---|---|
name |
str |
Transaction name |
status |
TransactionStatus |
Current status |
is_active |
bool |
Whether the transaction is currently active |
duration |
float \| None |
Duration in seconds (after commit/rollback) |
Methods:
def start(self) -> None
Start the transaction.
def commit(self) -> None
Commit the transaction.
def rollback(self) -> None
Roll back the transaction.
def add_operation(self, operation: Callable) -> None
Add an operation to the transaction.
def add_rollback_handler(self, handler: Callable) -> None
Add a handler called on rollback.
def add_commit_handler(self, handler: Callable) -> None
Add a handler called on commit.
TransactionGroup
Groups multiple transactions for batch execution.
Module: revitpy.api.transaction
class TransactionGroup:
def __init__(self, provider, name: str = "TransactionGroup") -> None
Methods:
def add_transaction(self, options: TransactionOptions | None = None) -> Transaction
Add a transaction to the group.
def start_all(self) -> None
Start all transactions in the group.
def commit_all(self) -> None
Commit all transactions in the group.
def rollback_all(self) -> None
Roll back all transactions in the group.
TransactionStatus
Module: revitpy.api.transaction
class TransactionStatus(Enum):
NOT_STARTED = "not_started"
STARTED = "started"
COMMITTED = "committed"
ROLLED_BACK = "rolled_back"
FAILED = "failed"
TransactionOptions
Module: revitpy.api.transaction
@dataclass
class TransactionOptions:
name: str = "Transaction"
description: str = ""
auto_commit: bool = False
timeout_seconds: float | None = None
retry_count: int = 0
retry_delay: float = 1.0
suppress_warnings: bool = False
QueryBuilder[T] (Core API)
Fluent query builder for filtering, sorting, and paginating Revit elements.
Module: revitpy.api.query
class QueryBuilder(Generic[T]):
def __init__(self, element_type: str, provider=None) -> None
Filter Methods:
def where(self, property_name: str, operator: str | FilterOperator, value: Any, case_sensitive: bool = True) -> "QueryBuilder[T]"
Add a filter condition.
def equals(self, property_name: str, value: Any) -> "QueryBuilder[T]"
def not_equals(self, property_name: str, value: Any) -> "QueryBuilder[T]"
def contains(self, property_name: str, value: str, case_sensitive: bool = True) -> "QueryBuilder[T]"
def starts_with(self, property_name: str, value: str) -> "QueryBuilder[T]"
def ends_with(self, property_name: str, value: str) -> "QueryBuilder[T]"
def in_values(self, property_name: str, values: list[Any]) -> "QueryBuilder[T]"
def is_null(self, property_name: str) -> "QueryBuilder[T]"
def is_not_null(self, property_name: str) -> "QueryBuilder[T]"
def regex(self, property_name: str, pattern: str) -> "QueryBuilder[T]"
Convenience filter methods for common operations.
Sort Methods:
def order_by(self, property_name: str, direction: SortDirection = SortDirection.ASCENDING) -> "QueryBuilder[T]"
def order_by_ascending(self, property_name: str) -> "QueryBuilder[T]"
def order_by_descending(self, property_name: str) -> "QueryBuilder[T]"
Pagination Methods:
def skip(self, count: int) -> "QueryBuilder[T]"
def take(self, count: int) -> "QueryBuilder[T]"
def distinct(self, property_name: str) -> "QueryBuilder[T]"
Terminal Methods:
def execute(self) -> list[T]
def count(self) -> int
def any(self) -> bool
def first(self) -> T
def first_or_default(self, default: T | None = None) -> T | None
def single(self) -> T
def to_list(self) -> list[T]
FilterOperator
Module: revitpy.api.query
class FilterOperator(Enum):
EQUALS = "equals"
NOT_EQUALS = "not_equals"
GREATER_THAN = "greater_than"
GREATER_THAN_OR_EQUAL = "greater_than_or_equal"
LESS_THAN = "less_than"
LESS_THAN_OR_EQUAL = "less_than_or_equal"
CONTAINS = "contains"
NOT_CONTAINS = "not_contains"
STARTS_WITH = "starts_with"
ENDS_WITH = "ends_with"
IN = "in"
NOT_IN = "not_in"
IS_NULL = "is_null"
IS_NOT_NULL = "is_not_null"
SortDirection
Module: revitpy.api.query
class SortDirection(Enum):
ASCENDING = "ascending"
DESCENDING = "descending"
Exceptions
Module: revitpy.api.exceptions
class RevitAPIError(Exception):
def __init__(self, message: str, cause: Exception | None = None) -> None
class TransactionError(RevitAPIError):
def __init__(self, message: str, transaction_name: str | None = None, cause: Exception | None = None) -> None
class ElementNotFoundError(RevitAPIError):
def __init__(self, element_id: int | None = None, element_type: str | None = None, cause: Exception | None = None) -> None
class ValidationError(RevitAPIError):
def __init__(self, message: str, field: str | None = None, value: Any = None, cause: Exception | None = None) -> None
class PermissionError(RevitAPIError):
def __init__(self, message: str, operation: str | None = None, cause: Exception | None = None) -> None
class ModelError(RevitAPIError):
def __init__(self, message: str, cause: Exception | None = None) -> None
class ConnectionError(RevitAPIError):
def __init__(self, message: str, cause: Exception | None = None) -> None
ORM Layer (revitpy.orm)
RevitContext
The primary ORM context for querying and managing Revit elements with change tracking, caching, and relationship support.
Module: revitpy.orm.context
class RevitContext:
def __init__(
self,
provider=None,
*,
config: ContextConfiguration | None = None,
cache_manager: CacheManager | None = None,
change_tracker: ChangeTracker | None = None,
relationship_manager: RelationshipManager | None = None,
unit_of_work=None,
) -> None
Can be used as a context manager (with RevitContext() as ctx:).
Query Methods:
def query(self, element_type: type[T]) -> "QueryBuilder[T]"
Create a query builder for the given element type.
def all(self, element_type: type[T]) -> list[T]
Get all elements of a type.
def where(self, element_type: type[T], predicate: Callable[[T], bool]) -> list[T]
Get elements matching a predicate.
def first(self) -> T
def first_or_default(self) -> T | None
def single(self) -> T
def count(self) -> int
def any(self) -> bool
def get_by_id(self, element_type: type[T], element_id: int) -> T | None
Get a specific element by type and ID.
Change Tracking Methods:
def attach(self, entity) -> None
def detach(self, entity) -> None
def add(self, entity) -> None
def remove(self, entity) -> None
def get_entity_state(self, entity) -> str
def accept_changes(self) -> None
def reject_changes(self) -> None
def save_changes(self) -> None
Relationship Methods:
def load_relationship(self, entity, relationship_name: str) -> Any
def configure_relationship(self, relationship_config) -> None
Cache Methods:
def clear_cache(self) -> None
def invalidate_cache(self, key: str) -> None
Other Methods:
def transaction(self, name: str = "Transaction") -> Transaction
def as_async(self) -> "AsyncRevitContext"
def dispose(self) -> None
ContextConfiguration
Module: revitpy.orm.context
@dataclass
class ContextConfiguration:
# Configuration fields for RevitContext behavior
create_context
Module: revitpy.orm.context
def create_context(provider=None, **kwargs) -> RevitContext
Factory function to create a configured RevitContext.
QueryBuilder[T] (ORM)
ORM query builder with lazy evaluation and async support. Distinct from the Core API QueryBuilder.
Module: revitpy.orm.query_builder
class QueryBuilder(Generic[T]):
def __init__(self, element_type: type[T], context=None) -> None
Fluent Methods:
def where(self, predicate: Callable[[T], bool]) -> "QueryBuilder[T]"
def select(self, selector: Callable[[T], Any]) -> "QueryBuilder[Any]"
def order_by(self, key_selector: Callable[[T], Any]) -> "QueryBuilder[T]"
def order_by_descending(self, key_selector: Callable[[T], Any]) -> "QueryBuilder[T]"
def skip(self, count: int) -> "QueryBuilder[T]"
def take(self, count: int) -> "QueryBuilder[T]"
def distinct(self, key_selector: Callable[[T], Any] | None = None) -> "QueryBuilder[T]"
Synchronous Terminal Methods:
def first(self) -> T
def first_or_default(self, default: T | None = None) -> T | None
def single(self) -> T
def single_or_default(self, default: T | None = None) -> T | None
def any(self, predicate: Callable[[T], bool] | None = None) -> bool
def all(self, predicate: Callable[[T], bool]) -> bool
def count(self) -> int
def to_list(self) -> list[T]
def to_dict(self, key_selector: Callable[[T], Any], value_selector: Callable[[T], Any] | None = None) -> dict
def group_by(self, key_selector: Callable[[T], Any]) -> dict[Any, list[T]]
Asynchronous Terminal Methods:
async def first_async(self) -> T
async def first_or_default_async(self, default: T | None = None) -> T | None
async def single_async(self) -> T
async def any_async(self, predicate: Callable[[T], bool] | None = None) -> bool
async def count_async(self) -> int
async def to_list_async(self) -> list[T]
async def to_dict_async(self, key_selector: Callable[[T], Any], value_selector: Callable[[T], Any] | None = None) -> dict
Streaming:
def as_streaming(self, batch_size: int = 100) -> "StreamingQuery[T]"
StreamingQuery[T]
Streaming query executor for processing large result sets in batches.
Module: revitpy.orm.query_builder
async def foreach_async(self, action: Callable[[T], Any]) -> None
async def to_list_async(self) -> list[T]
CacheManager
Manages caching of elements and query results with multiple eviction policies.
Module: revitpy.orm.cache
class CacheManager:
def __init__(self, config: CacheConfiguration | None = None) -> None
Properties:
| Property | Type | Description |
|---|---|---|
statistics |
CacheStatistics |
Cache hit/miss statistics |
size |
int |
Number of items in the cache |
Methods:
def get(self, key: str) -> Any | None
def set(self, key: str, value: Any, *, ttl_seconds: float | None = None, dependencies: list[str] | None = None) -> None
def delete(self, key: str) -> None
def invalidate(self, key: str) -> None
def invalidate_by_dependency(self, dependency: str) -> None
def invalidate_by_pattern(self, pattern: str) -> None
def clear(self) -> None
def contains(self, key: str) -> bool
def keys(self) -> list[str]
def add_invalidation_callback(self, callback: Callable) -> None
def remove_invalidation_callback(self, callback: Callable) -> None
def get_memory_usage_estimate(self) -> int
CacheConfiguration
Module: revitpy.orm.cache
@dataclass
class CacheConfiguration:
max_size: int = 1000
max_memory_mb: float = 100.0
default_ttl_seconds: float = 300.0
eviction_policy: EvictionPolicy = EvictionPolicy.LRU
enable_statistics: bool = True
cleanup_interval_seconds: float = 60.0
compression_enabled: bool = False
thread_safe: bool = True
CacheStatistics
Module: revitpy.orm.cache
Properties:
| Property | Type | Description |
|---|---|---|
hits |
int |
Number of cache hits |
misses |
int |
Number of cache misses |
hit_rate |
float |
Cache hit rate (0.0 to 1.0) |
evictions |
int |
Number of evictions |
invalidations |
int |
Number of invalidations |
memory_usage |
int |
Estimated memory usage in bytes |
uptime |
float |
Cache uptime in seconds |
EvictionPolicy
Module: revitpy.orm.cache
class EvictionPolicy(Enum):
LRU = "lru"
LFU = "lfu"
FIFO = "fifo"
TTL = "ttl"
SIZE_BASED = "size_based"
ChangeTracker
Tracks changes to entities for the unit of work pattern.
Module: revitpy.orm.change_tracker
class ChangeTracker:
def __init__(self) -> None
Properties:
| Property | Type | Description |
|---|---|---|
auto_track |
bool |
Whether to automatically track property changes |
has_changes |
bool |
Whether any tracked entities have changes |
changed_entities |
list |
List of entities with changes |
change_count |
int |
Total number of changes |
Methods:
def attach(self, entity: Any, entity_id: str | None = None) -> None
def detach(self, entity_id: str) -> None
def track_property_change(self, entity_id: str, property_name: str, old_value: Any, new_value: Any) -> None
def track_relationship_change(self, entity_id: str, relationship_name: str, change_type: ChangeType, related_entity_id: str) -> None
def mark_as_added(self, entity_id: str) -> None
def mark_as_deleted(self, entity_id: str) -> None
def get_entity_state(self, entity_id: str) -> str
def get_changes(self, entity_id: str) -> list[PropertyChange]
def get_all_changes(self) -> dict[str, list[PropertyChange]]
def accept_changes(self, entity_id: str | None = None) -> None
def reject_changes(self, entity_id: str | None = None) -> None
def clear(self) -> None
def create_batch_operation(self, name: str) -> None
def add_batch_operation(self, operation: Callable) -> None
def get_batch_operations(self) -> list
def clear_batch_operations(self) -> None
def add_change_callback(self, callback: Callable) -> None
def remove_change_callback(self, callback: Callable) -> None
def is_tracked(self, entity_id: str) -> bool
def get_tracked_count(self) -> int
ChangeType
Module: revitpy.orm.change_tracker
class ChangeType(Enum):
ADDED = "added"
MODIFIED = "modified"
DELETED = "deleted"
UNCHANGED = "unchanged"
PropertyChange
Module: revitpy.orm.change_tracker
@dataclass
class PropertyChange:
property_name: str
old_value: Any
new_value: Any
RelationshipManager
Manages relationships between Revit elements (one-to-one, one-to-many, many-to-many).
Module: revitpy.orm.relationships
class RelationshipManager:
def __init__(self) -> None
Methods:
def register_one_to_one(self, source_type: type, target_type: type, foreign_key: str, **kwargs) -> None
def register_one_to_many(self, source_type: type, target_type: type, foreign_key: str, **kwargs) -> None
def register_many_to_many(self, source_type: type, target_type: type, junction_type: type | None = None, **kwargs) -> None
def get_relationship(self, source_type: type, relationship_name: str) -> Relationship | None
def load_relationship(self, entity: Any, relationship_name: str, context=None) -> Any
async def load_relationship_async(self, entity: Any, relationship_name: str, context=None) -> Any
def invalidate_relationship(self, entity: Any, relationship_name: str) -> None
def invalidate_entity(self, entity: Any) -> None
def get_registered_relationships(self) -> list[Relationship]
Validation Models
Pydantic-based validation models for common Revit element types.
Module: revitpy.orm.validation
BaseElement
class BaseElement(BaseModel):
id: int | None = None
name: str
category: str = ""
level_id: int | None = None
family_name: str = ""
type_name: str = ""
created_at: datetime | None = None
modified_at: datetime | None = None
version: int = 1
is_valid: bool = True
state: str = "unchanged"
Methods:
def is_dirty(self) -> bool
def mark_dirty(self) -> None
def mark_clean(self) -> None
WallElement
class WallElement(BaseElement):
height: float = 0.0
length: float = 0.0
width: float = 0.0
area: float = 0.0
volume: float = 0.0
# Additional wall-specific fields
RoomElement
class RoomElement(BaseElement):
number: str = ""
area: float = 0.0
perimeter: float = 0.0
volume: float = 0.0
department: str = ""
occupancy: int = 0
# Additional room-specific fields
DoorElement
class DoorElement(BaseElement):
width: float = 0.0
height: float = 0.0
material: str = ""
fire_rating: str = ""
# Additional door-specific fields
WindowElement
class WindowElement(BaseElement):
width: float = 0.0
height: float = 0.0
glass_type: str = ""
# Additional window-specific fields
Factory Functions
def create_wall(**kwargs) -> WallElement
def create_room(**kwargs) -> RoomElement
def create_door(**kwargs) -> DoorElement
def create_window(**kwargs) -> WindowElement
ElementValidator
Module: revitpy.orm.validation
class ElementValidator:
# Validates elements against Pydantic models and custom constraints
ValidationLevel
Module: revitpy.orm.validation
class ValidationLevel(Enum):
# Defines validation strictness levels
ConstraintType
Module: revitpy.orm.validation
class ConstraintType(Enum):
# Defines types of validation constraints
Events (revitpy.events)
EventManager
Singleton event manager for registering and dispatching events.
Module: revitpy.events.manager
class EventManager:
# Singleton -- use EventManager() to get the instance
Properties:
| Property | Type | Description |
|---|---|---|
dispatcher |
object |
The internal event dispatcher |
is_running |
bool |
Whether the event manager is running |
stats |
dict |
Event processing statistics |
Lifecycle Methods:
def start(self, auto_discover: bool = False) -> None
def stop(self, timeout: float | None = None) -> None
Handler Registration:
def register_handler(self, handler: Callable, event_types: list[EventType] | None = None, priority: EventPriority = EventPriority.NORMAL) -> None
def register_function(self, func: Callable, event_types: list[EventType] | None = None) -> None
def unregister_handler(self, handler: Callable) -> None
def register_class_handlers(self, instance: Any) -> None
Event Dispatch:
def dispatch_event(self, event: EventData) -> EventResult
async def dispatch_event_async(self, event: EventData) -> EventResult
def emit(self, event_type: EventType, data: dict | None = None, **kwargs) -> EventResult
async def emit_async(self, event_type: EventType, data: dict | None = None, **kwargs) -> EventResult
Discovery:
def add_discovery_path(self, path: str) -> None
def discover_handlers(self) -> None
Listener Management:
def add_listener(self, event_type: EventType, listener: Callable) -> None
def remove_listener(self, event_type: EventType, listener: Callable) -> None
Revit Integration:
def connect_to_revit(self, application) -> None
def disconnect_from_revit(self) -> None
Debugging:
def enable_debug(self) -> None
def disable_debug(self) -> None
def clear_event_queue(self) -> None
def reset_statistics(self) -> None
def get_registered_handlers(self) -> list
EventType
Module: revitpy.events.types
class EventType(Enum):
# Document events
DOCUMENT_OPENED = "document_opened"
DOCUMENT_CLOSED = "document_closed"
DOCUMENT_SAVED = "document_saved"
DOCUMENT_CREATED = "document_created"
DOCUMENT_MODIFIED = "document_modified"
# Element events
ELEMENT_CREATED = "element_created"
ELEMENT_MODIFIED = "element_modified"
ELEMENT_DELETED = "element_deleted"
# Transaction events
TRANSACTION_STARTED = "transaction_started"
TRANSACTION_COMMITTED = "transaction_committed"
TRANSACTION_ROLLED_BACK = "transaction_rolled_back"
# Parameter events
PARAMETER_CHANGED = "parameter_changed"
# View events
VIEW_ACTIVATED = "view_activated"
VIEW_DEACTIVATED = "view_deactivated"
# Selection events
SELECTION_CHANGED = "selection_changed"
# Application events
APPLICATION_INITIALIZED = "application_initialized"
APPLICATION_CLOSING = "application_closing"
IDLE_EVENT = "idle_event"
# Custom events
CUSTOM = "custom"
EXTENSION_EVENT = "extension_event"
EventPriority
Module: revitpy.events.types
class EventPriority(Enum):
LOWEST = 0
LOW = 25
NORMAL = 50
HIGH = 75
HIGHEST = 100
EventResult
Module: revitpy.events.types
class EventResult(Enum):
CONTINUE = "continue"
STOP = "stop"
CANCEL = "cancel"
EventData
Module: revitpy.events.types
@dataclass
class EventData:
event_type: EventType
event_id: str
timestamp: float
source: Any = None
data: dict = field(default_factory=dict)
cancellable: bool = False
cancelled: bool = False
Methods:
def cancel(self) -> None
def get_data(self, key: str, default: Any = None) -> Any
def set_data(self, key: str, value: Any) -> None
Specialized Event Data Classes:
DocumentEventData(EventData)– document-specific event dataElementEventData(EventData)– element-specific event dataTransactionEventData(EventData)– transaction-specific event dataParameterEventData(EventData)– parameter change event dataViewEventData(EventData)– view-specific event dataSelectionEventData(EventData)– selection change event data
Event Decorators
Module: revitpy.events.decorators
def event_handler(
event_types: list[EventType] | EventType | None = None,
priority: EventPriority = EventPriority.NORMAL,
event_filter: Callable | None = None,
max_errors: int = 3,
enabled: bool = True,
) -> Callable
Decorator to register a function as an event handler.
def async_event_handler(
event_types: list[EventType] | EventType | None = None,
priority: EventPriority = EventPriority.NORMAL,
event_filter: Callable | None = None,
max_errors: int = 3,
enabled: bool = True,
) -> Callable
Decorator to register an async function as an event handler.
def event_filter(filter_instance: Callable) -> Callable
Decorator to attach a filter to an event handler.
def throttled_handler(interval_seconds: float) -> Callable
Decorator to throttle event handler execution to a minimum interval.
def conditional_handler(condition: Callable[..., bool]) -> Callable
Decorator to conditionally execute an event handler.
def retry_on_error(max_retries: int = 3, delay_seconds: float = 1.0) -> Callable
Decorator to retry an event handler on error.
def log_events(log_level: str = "INFO") -> Callable
Decorator to log event handler invocations.
Convenience Decorators:
def on_element_created() -> Callable
def on_element_modified() -> Callable
def on_element_deleted() -> Callable
def on_parameter_changed() -> Callable
def on_document_opened() -> Callable
def on_document_saved() -> Callable
Extensions (revitpy.extensions)
Extension
Abstract base class for RevitPy extensions with lifecycle management.
Module: revitpy.extensions.extension
class Extension(ABC):
def __init__(self, metadata: ExtensionMetadata | None = None) -> None
Lifecycle Methods (abstract, override in subclasses):
def load(self) -> None
def activate(self) -> None
def deactivate(self) -> None
def dispose(self) -> None
Internal Lifecycle (called by ExtensionManager):
def load_extension(self) -> None
def activate_extension(self) -> None
def deactivate_extension(self) -> None
def dispose_extension(self) -> None
Component Access:
def get_command(self, name: str) -> Any | None
def get_service(self, name: str) -> Any | None
def get_tool(self, name: str) -> Any | None
def get_analyzer(self, name: str) -> Any | None
def get_commands(self) -> dict[str, Any]
def get_services(self) -> dict[str, Any]
def get_tools(self) -> dict[str, Any]
def get_analyzers(self) -> dict[str, Any]
Lifecycle Callbacks:
def on_load(self) -> None
def on_activation(self) -> None
def on_deactivation(self) -> None
def on_disposal(self) -> None
ExtensionMetadata
Module: revitpy.extensions.extension
@dataclass
class ExtensionMetadata:
name: str
version: str
description: str = ""
author: str = ""
# Additional metadata fields
ExtensionStatus
Module: revitpy.extensions.extension
class ExtensionStatus(Enum):
# 9 status values covering the full extension lifecycle
UNLOADED = "unloaded"
LOADING = "loading"
LOADED = "loaded"
ACTIVATING = "activating"
ACTIVE = "active"
DEACTIVATING = "deactivating"
INACTIVE = "inactive"
DISPOSING = "disposing"
DISPOSED = "disposed"
ExtensionManager
Singleton manager for discovering, loading, and managing extensions.
Module: revitpy.extensions.manager
class ExtensionManager:
# Singleton -- use ExtensionManager() to get the instance
Methods:
def initialize(self) -> None
def shutdown(self) -> None
def discover_extensions(self, path: str | None = None) -> list[Extension]
def load_extension(self, extension: Extension | str) -> None
def unload_extension(self, extension_name: str) -> None
def activate_extension(self, extension_name: str) -> None
def deactivate_extension(self, extension_name: str) -> None
def get_extension(self, extension_name: str) -> Extension | None
def get_extensions(self) -> list[Extension]
def get_active_extensions(self) -> list[Extension]
def get_extensions_by_status(self, status: ExtensionStatus) -> list[Extension]
def has_extension(self, extension_name: str) -> bool
def is_extension_active(self, extension_name: str) -> bool
def get_statistics(self) -> dict[str, Any]
def get_extension_info(self, extension_name: str) -> dict[str, Any]
Extension Decorators
Module: revitpy.extensions.decorators
def extension(
name: str,
version: str = "1.0.0",
description: str = "",
author: str = "",
dependencies: list[str] | None = None,
) -> Callable
Class decorator to register a class as an extension.
def command(
name: str,
description: str = "",
icon: str = "",
tooltip: str = "",
shortcut: str = "",
category: str = "",
enabled: bool = True,
visible: bool = True,
) -> Callable
Decorator to register a method as a command.
def service(
name: str,
description: str = "",
auto_start: bool = False,
singleton: bool = True,
dependencies: list[str] | None = None,
) -> Callable
Decorator to register a method as a service.
def tool(
name: str,
description: str = "",
icon: str = "",
tooltip: str = "",
category: str = "",
interactive: bool = False,
preview: bool = False,
) -> Callable
Decorator to register a method as a tool.
def analyzer(
name: str,
description: str = "",
element_types: list[str] | None = None,
categories: list[str] | None = None,
real_time: bool = False,
on_demand: bool = True,
) -> Callable
Decorator to register a method as an analyzer.
def panel(
name: str,
title: str = "",
width: int = 300,
height: int = 400,
resizable: bool = True,
dockable: bool = True,
floating: bool = False,
) -> Callable
Decorator to register a method as a panel.
def startup(priority: int = 0) -> Callable
Decorator to mark a method to run on extension startup.
def shutdown(priority: int = 0) -> Callable
Decorator to mark a method to run on extension shutdown.
def config(
key: str,
default_value: Any = None,
description: str = "",
required: bool = False,
validator: Callable | None = None,
) -> Callable
Decorator to register a configuration option.
def permission(
name: str,
description: str = "",
required: bool = True,
category: str = "",
) -> Callable
Decorator to declare a required permission.
def cache(
ttl: float = 300.0,
max_size: int = 100,
key_func: Callable | None = None,
) -> Callable
Decorator to cache method results.
Async Support (revitpy.async_support)
AsyncRevit
Asynchronous interface for Revit operations.
Module: revitpy.async_support.async_revit
class AsyncRevit:
def __init__(self) -> None
Properties:
| Property | Type | Description |
|---|---|---|
api |
RevitAPI |
The underlying RevitAPI instance |
is_connected |
bool |
Whether connected to Revit |
task_queue |
TaskQueue |
The internal task queue |
Initialization:
async def initialize(self, max_concurrent_tasks: int = 4, revit_application=None) -> None
async def shutdown(self, timeout: float | None = None) -> None
Document Operations:
async def open_document_async(self, file_path: str) -> Any
async def create_document_async(self, template_path: str | None = None) -> Any
async def save_document_async(self, provider=None) -> None
async def close_document_async(self, provider=None, save_changes: bool = True) -> None
Element Operations:
async def get_elements_async(self, element_type: str | None = None) -> list
async def query_elements_async(self, element_type: str, **filters) -> list
async def update_elements_async(self, elements: list, **updates) -> None
Transaction:
def async_transaction(self, name: str = "Transaction") -> Any
async def execute_in_transaction_async(self, func: Callable, name: str = "Transaction") -> Any
Background Tasks:
async def run_background_task(self, func: Callable, *args, **kwargs) -> Any
async def wait_for_background_task(self, task_id: str, timeout: float | None = None) -> Any
async def start_background_task(self, func: Callable, *args, **kwargs) -> str
async def cancel_background_task(self, task_id: str) -> None
Context Managers:
def element_scope(self, elements: list, auto_save: bool = True) -> Any
def progress_scope(self, total: int, message: str = "") -> Any
Batch Processing:
async def batch_process(self, items: list, processor: Callable, batch_size: int = 100) -> list
Async Decorators
Module: revitpy.async_support.decorators
def async_revit_operation(
timeout: float | None = None,
retry_count: int = 0,
retry_delay: float = 1.0,
cancellation_token: CancellationToken | None = None,
progress_reporter: ProgressReporter | None = None,
) -> Callable
Decorator for async Revit operations with timeout, retry, and progress support.
def background_task(
priority: TaskPriority = TaskPriority.NORMAL,
timeout: float | None = None,
retry_count: int = 0,
retry_delay: float = 1.0,
progress: bool = False,
task_queue: TaskQueue | None = None,
) -> Callable
Decorator to run a function as a background task.
def revit_transaction(
name: str = "Transaction",
auto_commit: bool = True,
timeout: float | None = None,
) -> Callable
Decorator to wrap a function in a Revit transaction.
def rate_limited(max_calls: int, time_window: float) -> Callable
Decorator to rate-limit function calls.
def cache_result(ttl: float = 300.0, max_size: int = 100) -> Callable
Decorator to cache function results.
Async Context Managers
Module: revitpy.async_support.context_managers
async def async_transaction(
provider,
name: str = "Transaction",
auto_commit: bool = True,
timeout: float | None = None,
retry_count: int = 0,
retry_delay: float = 1.0,
cancellation_token: CancellationToken | None = None,
) -> AsyncContextManager
async def async_element_scope(
elements: list,
auto_save: bool = True,
rollback_on_error: bool = True,
) -> AsyncContextManager
async def async_progress_scope(
total: int,
message: str = "",
console_output: bool = True,
) -> AsyncContextManager
async def async_cancellation_scope(
timeout: float | None = None,
reason: str = "",
) -> AsyncContextManager
async def async_batch_operations(
batch_size: int = 100,
delay_between_batches: float = 0.0,
) -> AsyncContextManager
async def async_resource_scope(*resources) -> AsyncContextManager
TaskQueue
Manages a queue of asynchronous tasks with priority ordering.
Module: revitpy.async_support.task_queue
class TaskQueue:
def __init__(self, max_concurrent: int = 4) -> None
Properties:
| Property | Type | Description |
|---|---|---|
is_running |
bool |
Whether the queue is processing |
pending_count |
int |
Number of pending tasks |
running_count |
int |
Number of running tasks |
completed_count |
int |
Number of completed tasks |
stats |
dict |
Queue statistics |
Methods:
async def enqueue(self, task: Task) -> str
def enqueue_sync(self, task: Task) -> str
async def submit(self, func: Callable, *args, **kwargs) -> str
async def wait_for_task(self, task_id: str, timeout: float | None = None) -> TaskResult
def get_task_status(self, task_id: str) -> TaskStatus
def get_task_result(self, task_id: str) -> TaskResult | None
async def start(self) -> None
async def stop(self, timeout: float | None = None) -> None
def clear_completed(self, older_than: float | None = None) -> int
TaskStatus
Module: revitpy.async_support.task_queue
class TaskStatus(Enum):
PENDING = "pending"
RUNNING = "running"
COMPLETED = "completed"
FAILED = "failed"
CANCELLED = "cancelled"
TaskPriority
Module: revitpy.async_support.task_queue
class TaskPriority(Enum):
LOW = 0
NORMAL = 1
HIGH = 2
CRITICAL = 3
TaskResult
Module: revitpy.async_support.task_queue
@dataclass
class TaskResult:
task_id: str
status: TaskStatus
result: Any = None
error: Exception | None = None
duration: float = 0.0
ProgressReporter
Reports progress for long-running operations.
Module: revitpy.async_support.progress
class ProgressReporter:
def __init__(self, total: int = 100) -> None
Properties:
| Property | Type | Description |
|---|---|---|
current |
int |
Current progress value |
total |
int |
Total progress value |
percentage |
float |
Progress as a percentage (0.0-100.0) |
state |
ProgressState |
Current progress state |
last_report |
ProgressReport \| None |
Most recent progress report |
elapsed_time |
float |
Elapsed time in seconds |
estimated_remaining |
float \| None |
Estimated remaining time |
Methods:
def add_callback(self, callback: Callable) -> None
def remove_callback(self, callback: Callable) -> None
def set_total(self, total: int) -> None
def start(self) -> None
def increment(self, amount: int = 1) -> None
def set_progress(self, current: int) -> None
def report_progress(self, current: int, message: str = "") -> None
def report(self, message: str = "") -> None
def complete(self) -> None
def fail(self, error: str = "") -> None
def cancel(self) -> None
ProgressState
Module: revitpy.async_support.progress
class ProgressState(Enum):
NOT_STARTED = "not_started"
IN_PROGRESS = "in_progress"
COMPLETED = "completed"
FAILED = "failed"
CANCELLED = "cancelled"
ProgressReport
Module: revitpy.async_support.progress
@dataclass
class ProgressReport:
current: int
total: int
percentage: float
message: str
state: ProgressState
elapsed_time: float
estimated_remaining: float | None
CancellationToken
Token for cooperative cancellation of async operations.
Module: revitpy.async_support.cancellation
class CancellationToken:
# Created via CancellationTokenSource
Properties:
| Property | Type | Description |
|---|---|---|
is_cancelled |
bool |
Whether cancellation has been requested |
cancelled_at |
float \| None |
Timestamp when cancelled |
reason |
str |
Reason for cancellation |
Methods:
def throw_if_cancellation_requested(self) -> None
Raises OperationCancelledError if cancellation has been requested.
def register_callback(self, callback: Callable) -> None
Register a callback to be called when cancellation is requested.
CancellationTokenSource
Creates and controls CancellationToken instances.
Module: revitpy.async_support.cancellation
class CancellationTokenSource:
def __init__(self) -> None
Properties:
| Property | Type | Description |
|---|---|---|
token |
CancellationToken |
The cancellation token |
is_cancelled |
bool |
Whether cancellation has been requested |
Methods:
def cancel(self, reason: str = "") -> None
Request cancellation.
def cancel_after(self, timeout: float, reason: str = "") -> None
Request cancellation after a timeout.
def dispose(self) -> None
Dispose of resources.
OperationCancelledError
Module: revitpy.async_support.cancellation
class OperationCancelledError(Exception):
pass
Utility Functions
Module: revitpy.async_support.cancellation
def combine_tokens(*tokens: CancellationToken) -> CancellationToken
Combine multiple tokens into one that cancels when any source cancels.
def with_cancellation(token: CancellationToken) -> Callable
Decorator to add cancellation support to an async function.
Testing (revitpy.testing)
MockRevit
Mock Revit environment for testing without an actual Revit installation.
Module: revitpy.testing.mock_revit
class MockRevit:
def __init__(self) -> None
Properties:
| Property | Type | Description |
|---|---|---|
application |
MockApplication |
The mock application instance |
active_document |
MockDocument \| None |
The currently active document |
Methods:
def create_document(self, title: str = "TestDocument.rvt") -> MockDocument
Create a test document.
def create_element(
self,
name: str = "TestElement",
category: str = "Generic",
element_type: str = "Element",
parameters: dict[str, Any] | None = None,
) -> MockElement
Create a test element. If an active document exists, the element is added to it.
def create_elements(
self,
count: int,
name_prefix: str = "Element",
category: str = "Generic",
element_type: str = "Element",
) -> list[MockElement]
Create multiple test elements with sequential names.
def load_fixture(self, fixture_name: str, fixture_data: Any) -> None
def get_fixture(self, fixture_name: str) -> Any
Load and retrieve test fixtures.
def save_state(self, file_path: str) -> None
def load_state(self, file_path: str) -> None
Save/load mock Revit state to/from JSON files.
def reset(self) -> None
Reset mock environment to initial state.
def add_event_handler(self, handler: Callable) -> None
def trigger_event(self, event_type: str, event_data: Any) -> None
Add and trigger event handlers for testing.
def get_statistics(self) -> dict[str, Any]
Returns dict with keys: documents, total_elements, fixtures, event_handlers, has_active_document.
MockDocument
Module: revitpy.testing.mock_revit
class MockDocument:
def __init__(
self,
title: str = "MockDocument.rvt",
path: str = "",
is_family_document: bool = False,
) -> None
Attributes: Title, PathName, IsFamilyDocument
Methods:
def GetElements(self, filter_criteria=None) -> list[MockElement]
def GetElement(self, element_id: int | MockElementId) -> MockElement | None
def AddElement(self, element: MockElement) -> MockElement
def CreateElement(self, name: str = "NewElement", category: str = "Generic", element_type: str = "Element") -> MockElement
def Delete(self, element_ids: list[int | MockElementId]) -> None
def Save(self) -> bool
def Close(self, save_changes: bool = True) -> bool
def StartTransaction(self, name: str = "Transaction") -> MockTransaction
def IsModified(self) -> bool
def GetElementCount(self) -> int
def GetElementsByCategory(self, category: str) -> list[MockElement]
def GetElementsByType(self, element_type: str) -> list[MockElement]
def to_dict(self) -> dict[str, Any]
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "MockDocument"
MockElement
Module: revitpy.testing.mock_revit
class MockElement:
def __init__(
self,
element_id: int = None,
name: str = "MockElement",
category: str = "Generic",
element_type: str = "Element",
) -> None
Attributes: Id (MockElementId), Name, Category, ElementType
Methods:
def GetParameterValue(self, parameter_name: str) -> Any
def SetParameterValue(self, parameter_name: str, value: Any) -> None
def GetParameter(self, parameter_name: str) -> MockParameter | None
def SetParameter(self, parameter_name: str, parameter: MockParameter) -> None
def GetAllParameters(self) -> dict[str, MockParameter]
def HasParameter(self, parameter_name: str) -> bool
def GetProperty(self, property_name: str) -> Any
def SetProperty(self, property_name: str, value: Any) -> None
def to_dict(self) -> dict[str, Any]
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "MockElement"
MockApplication
Module: revitpy.testing.mock_revit
class MockApplication:
def __init__(self) -> None
Properties:
| Property | Type | Description |
|---|---|---|
ActiveDocument |
MockDocument \| None |
The active document |
Methods:
def OpenDocumentFile(self, file_path: str) -> MockDocument
def CreateDocument(self, template_path: str | None = None) -> MockDocument
def GetOpenDocuments(self) -> list[MockDocument]
def CloseDocument(self, document: MockDocument) -> bool
MockTransaction
Module: revitpy.testing.mock_revit
class MockTransaction:
def __init__(self, name: str = "MockTransaction") -> None
Attributes: name, is_started, is_committed, is_rolled_back
Methods:
def Start(self) -> bool
def Commit(self) -> bool
def RollBack(self) -> bool
MockParameter
Module: revitpy.testing.mock_revit
@dataclass
class MockParameter:
name: str
value: Any = None
type_name: str = "String"
storage_type: str = "String"
is_read_only: bool = False
Methods:
def AsString(self) -> str
def AsDouble(self) -> float
def AsInteger(self) -> int
def AsValueString(self) -> str
MockElementId
Module: revitpy.testing.mock_revit
class MockElementId:
def __init__(self, value: int) -> None
Attributes: IntegerValue
Performance (revitpy.performance)
Module: revitpy.performance
The performance module exports the following classes:
| Class | Description |
|---|---|
PerformanceOptimizer |
Optimization engine |
OptimizationConfig |
Configuration for the optimizer |
BenchmarkSuite |
Suite of performance benchmarks |
BenchmarkRunner |
Runs benchmark suites |
MemoryManager |
Memory management utilities |
MemoryLeakDetector |
Detects memory leaks |
LatencyTracker |
Tracks operation latency |
LatencyBenchmark |
Latency benchmark definitions |
IntelligentCacheManager |
Advanced caching with adaptive policies |
CacheConfiguration |
Cache configuration (performance module) |
MetricsCollector |
Collects performance metrics |
PerformanceMetrics |
Container for collected metrics |
PerformanceMonitor |
Real-time performance monitoring |
AlertingSystem |
Performance alerting |
RevitPyProfiler |
Code profiling |
ProfileReport |
Profiling results |
Configuration (revitpy.config)
Exports: Config, ConfigManager
These classes are exported from revitpy.__init__ and handle framework configuration. See the Developer Setup Guide for configuration details.
Quantity Extraction (revitpy.extract)
QuantityExtractor
Extract measured quantities (area, volume, length, count, weight) from Revit elements using duck-typed attribute access.
Module: revitpy.extract.quantities
class QuantityExtractor:
def __init__(self, context: Any | None = None) -> None
Methods:
def extract(self, elements: list[Any], quantity_types: list[QuantityType] | None = None) -> list[QuantityItem]
Extract quantities from elements. Defaults to all quantity types when quantity_types is None.
def extract_grouped(self, elements: list[Any], group_by: AggregationLevel = AggregationLevel.CATEGORY, quantity_types: list[QuantityType] | None = None) -> dict[str, list[QuantityItem]]
Extract and group quantities by aggregation level (category, level, system, element, or building).
def summarize(self, items: list[QuantityItem]) -> dict[str, float]
Summarize quantities by type, summing values. Returns a dict mapping quantity type names to summed values.
async def extract_async(self, elements: list[Any], quantity_types: list[QuantityType] | None = None, progress: Callable[[int, int], None] | None = None) -> list[QuantityItem]
Async version of extract with optional progress reporting callback (current, total).
MaterialTakeoff
Extract and process material quantities from Revit elements, with aggregation and industry-standard classification.
Module: revitpy.extract.materials
class MaterialTakeoff:
def __init__(self, context: Any | None = None) -> None
Methods:
def extract(self, elements: list[Any]) -> list[MaterialQuantity]
Extract material data from elements. Elements are duck-typed with optional material_name, material_volume, material_area, material_mass, and category attributes.
def aggregate(self, materials: list[MaterialQuantity]) -> list[MaterialQuantity]
Aggregate material quantities by material name, summing volume, area, and mass.
def classify(self, materials: list[MaterialQuantity], system: str = "UniFormat") -> list[MaterialQuantity]
Classify materials against a standard system ("UniFormat" or "MasterFormat"). Returns new list with classification_code and classification_system set.
CostEstimator
Map extracted quantities to cost data, producing itemized cost breakdowns and aggregated summaries.
Module: revitpy.extract.costs
class CostEstimator:
def __init__(self, cost_database: dict[str, float] | Path | None = None) -> None
Properties:
| Property | Type | Description |
|---|---|---|
database |
dict[str, float] |
Copy of the current cost database |
Methods:
def load_database(self, path: Path) -> None
Load cost data from a file. Supports CSV, JSON, and YAML formats (auto-detected from extension).
def estimate(self, quantities: list[QuantityItem], aggregation: AggregationLevel = AggregationLevel.CATEGORY) -> CostSummary
Map quantities to costs and produce a summary with itemized costs and aggregated totals by category, system, and level.
DataExporter
Export tabular data to CSV, JSON, Excel, Parquet, or plain dicts.
Module: revitpy.extract.exporters
class DataExporter:
# No constructor arguments required
Methods:
def export(self, data: list[dict[str, Any]], config: ExportConfig) -> Path | list[dict[str, Any]]
Export data according to the given configuration. Returns a Path for file formats, or list[dict] for DICT format.
def to_csv(self, data: list[dict[str, Any]], path: Path | None, *, include_headers: bool = True, decimal_places: int = 2) -> Path
Export data to CSV.
def to_json(self, data: list[dict[str, Any]], path: Path | None, *, decimal_places: int = 2) -> Path
Export data to JSON.
def to_excel(self, data: list[dict[str, Any]], path: Path | None, *, sheet_name: str = "Sheet1", include_headers: bool = True) -> Path
Export data to Excel (xlsx). Requires the optional openpyxl dependency.
def to_parquet(self, data: list[dict[str, Any]], path: Path | None) -> Path
Export data to Parquet. Requires the optional pyarrow dependency.
def to_dicts(self, data: list[dict[str, Any]]) -> list[dict[str, Any]]
Return data as a list of dicts (shallow copy passthrough).
IFC Interoperability (revitpy.ifc)
IfcElementMapper
Bidirectional mapping between RevitPy element types and IFC entity types, with custom property map support and type registration.
Module: revitpy.ifc.mapper
class IfcElementMapper:
def __init__(self) -> None
Properties:
| Property | Type | Description |
|---|---|---|
registered_types |
list[str] |
All registered RevitPy type names |
registered_ifc_types |
list[str] |
All registered IFC entity type names |
Methods:
def register_mapping(self, revitpy_type: str, ifc_entity_type: str, property_map: dict[str, str] | None = None, *, bidirectional: bool = True) -> None
Register a custom mapping between a RevitPy type and IFC entity type.
def get_mapping(self, revitpy_type: str) -> IfcMapping | None
Get the IFC mapping for a RevitPy type.
def get_ifc_type(self, revitpy_type: str) -> str | None
Get the IFC entity type name for a RevitPy type.
def get_revitpy_type(self, ifc_entity_type: str) -> str | None
Get the RevitPy type name for an IFC entity type.
def to_ifc(self, element: Any, ifc_file: Any, config: IfcExportConfig | None = None) -> Any
Convert a RevitPy element to an IFC entity. Requires ifcopenshell.
def from_ifc(self, ifc_entity: Any, target_type: str | None = None) -> dict[str, Any]
Convert an IFC entity to a dict representation. Consults the reverse registry when target_type is not provided.
IfcExporter
Export RevitPy elements to IFC files using ifcopenshell.
Module: revitpy.ifc.exporter
class IfcExporter:
def __init__(self, mapper: IfcElementMapper | None = None, config: IfcExportConfig | None = None) -> None
Properties:
| Property | Type | Description |
|---|---|---|
mapper |
IfcElementMapper |
The element mapper used by this exporter |
config |
IfcExportConfig |
The export configuration |
Methods:
def export(self, elements: list[Any], output_path: str | Path, version: IfcVersion = IfcVersion.IFC4) -> Path
Export elements to an IFC file. Creates project structure (IfcProject, IfcSite, IfcBuilding) and converts each element via the mapper.
async def export_async(self, elements: list[Any], output_path: str | Path, version: IfcVersion = IfcVersion.IFC4, progress: Callable[[int, int], None] | None = None) -> Path
Export elements to an IFC file asynchronously with optional progress reporting.
IfcImporter
Import elements from IFC files and convert them to RevitPy element dictionaries.
Module: revitpy.ifc.importer
class IfcImporter:
def __init__(self, mapper: IfcElementMapper | None = None, config: IfcImportConfig | None = None) -> None
Properties:
| Property | Type | Description |
|---|---|---|
mapper |
IfcElementMapper |
The element mapper used by this importer |
config |
IfcImportConfig |
The import configuration |
Methods:
def import_file(self, path: str | Path) -> list[dict[str, Any]]
Import elements from an IFC file. Parses the file with ifcopenshell and converts entities via the mapper.
async def import_file_async(self, path: str | Path) -> list[dict[str, Any]]
Import elements from an IFC file asynchronously.
IdsValidator
Validate elements against IDS (Information Delivery Specification) requirements by inspecting their properties.
Module: revitpy.ifc.validator
class IdsValidator:
def __init__(self) -> None
Methods:
def validate(self, elements: list[Any], requirements: list[IdsRequirement]) -> list[IdsValidationResult]
Validate elements against a list of IDS requirements. Each element is checked against every applicable requirement.
def validate_from_file(self, elements: list[Any], ids_path: str | Path) -> list[IdsValidationResult]
Validate elements against requirements loaded from a JSON file.
BcfManager
Create, read, and write BCF (BIM Collaboration Format) issues with simplified BCF 2.1 compatible workflow.
Module: revitpy.ifc.bcf
class BcfManager:
def __init__(self) -> None
Properties:
| Property | Type | Description |
|---|---|---|
issues |
list[BcfIssue] |
All managed issues |
Methods:
def create_issue(self, title: str, description: str = "", *, author: str = "", status: str = "Open", assigned_to: str = "", element_ids: list[str] | None = None) -> BcfIssue
Create a new BCF issue and add it to the managed list.
def read_bcf(self, path: str | Path) -> list[BcfIssue]
Read BCF issues from a file. Supports .bcf/.bcfzip ZIP archives and .json files.
def write_bcf(self, issues: list[BcfIssue] | None = None, path: str | Path = "issues.bcf") -> Path
Write BCF issues to a ZIP archive containing XML markup.xml per topic. Defaults to all managed issues.
IfcDiff
Compare two IFC model states and produce a structured diff identifying added, modified, and removed entities.
Module: revitpy.ifc.diff
class IfcDiff:
def __init__(self) -> None
Methods:
def compare(self, old_elements: list[Any], new_elements: list[Any]) -> IfcDiffResult
Compare two element lists and return differences. Elements are matched by id or global_id.
def compare_files(self, old_path: str | Path, new_path: str | Path) -> IfcDiffResult
Compare two IFC files and return differences. Both files are imported and compared at the property level.
AI & MCP Server (revitpy.ai)
RevitTools
Registry of tools that can be invoked through the MCP server. Manages tool definitions, validates arguments, dispatches execution, and converts tools to MCP-compatible JSON Schema format.
Module: revitpy.ai.tools
class RevitTools:
def __init__(self, context: Any = None) -> None
Methods:
def register_tool(self, definition: ToolDefinition, handler: Callable) -> None
Register a tool with its handler callable.
def get_tool(self, name: str) -> ToolDefinition | None
Return the definition of a registered tool, or None.
def list_tools(self) -> list[ToolDefinition]
Return all registered tool definitions.
def execute_tool(self, name: str, arguments: dict[str, Any]) -> ToolResult
Execute a tool by name. Validates required parameters, invokes the handler, and wraps the outcome in a ToolResult.
def to_mcp_tool_list(self) -> list[dict[str, Any]]
Convert all tools to MCP-format JSON Schema definitions.
SafetyGuard
Validates tool calls against a safety policy. Supports READ_ONLY, CAUTIOUS, and permissive modes, and provides an undo stack for rollback.
Module: revitpy.ai.safety
class SafetyGuard:
def __init__(self, config: SafetyConfig | None = None) -> None
Properties:
| Property | Type | Description |
|---|---|---|
config |
SafetyConfig |
The active safety configuration |
Methods:
def validate_tool_call(self, tool: ToolDefinition, arguments: dict[str, Any]) -> bool
Check whether a tool call is allowed under the current policy. Raises SafetyViolationError when blocked.
def preview_changes(self, tool: ToolDefinition, arguments: dict[str, Any]) -> dict[str, Any]
Return a dry-run preview of the changes a tool call would make.
def push_undo(self, operation: dict[str, Any]) -> None
Push an operation onto the undo stack (bounded by SafetyConfig.max_undo_stack).
def undo_last(self) -> dict[str, Any] | None
Pop and return the most recent undo entry, or None.
def get_undo_stack(self) -> list[dict[str, Any]]
Return a copy of the current undo stack.
PromptLibrary
Manages and renders Jinja2 prompt templates for LLM interactions within the MCP server. Built-in templates are registered at construction time.
Module: revitpy.ai.prompts
class PromptLibrary:
def __init__(self) -> None
Methods:
def render(self, template_name: str, /, **kwargs: Any) -> str
Render a template by name. Raises PromptError if the template does not exist or rendering fails.
def register_template(self, name: str, template: str) -> None
Register or overwrite a Jinja2 template.
def get_template(self, name: str) -> str | None
Return the raw source of a template, or None.
def list_templates(self) -> list[str]
Return sorted list of all template names.
def to_mcp_prompts_list(self) -> list[dict[str, Any]]
Convert templates to MCP-format prompt definitions.
McpServer
Asynchronous WebSocket server implementing a subset of the Model Context Protocol, exposing tools, prompts, and safety controls.
Module: revitpy.ai.server
class McpServer:
def __init__(self, tools: RevitTools, *, config: McpServerConfig | None = None, safety_guard: SafetyGuard | None = None, prompt_library: PromptLibrary | None = None) -> None
Properties:
| Property | Type | Description |
|---|---|---|
config |
McpServerConfig |
The active server configuration |
connections |
set[Any] |
Set of active WebSocket connections |
Methods:
async def start(self) -> None
Start the WebSocket server on the configured host and port.
async def stop(self, timeout: float = 5.0) -> None
Gracefully stop the server. Waits up to timeout seconds for connections to close.
Supports async context manager protocol (async with McpServer(...) as server:).
Sustainability (revitpy.sustainability)
CarbonCalculator
Calculate embodied carbon for building materials using EPD database lookups. Supports mass-based and volume-based calculation methods.
Module: revitpy.sustainability.carbon
class CarbonCalculator:
def __init__(self, epd_database: EpdDatabase | None = None) -> None
Methods:
def calculate(self, materials: list[MaterialData], lifecycle_stages: list[LifecycleStage] | None = None) -> list[CarbonResult]
Calculate embodied carbon for a list of materials. Defaults to A1-A3 lifecycle stages. Looks up EPD records and computes carbon as mass * gwp_per_kg or volume * gwp_per_m3.
def summarize(self, results: list[CarbonResult]) -> BuildingCarbonSummary
Aggregate carbon results into a building-level summary with totals by material, system, level, and lifecycle stage.
def benchmark(self, summary: BuildingCarbonSummary, building_area_m2: float, building_type: str = "default") -> CarbonBenchmark
Benchmark building carbon against RIBA 2030 Climate Challenge targets. Returns rating (Excellent, Good, Acceptable, Below Average, Poor).
async def calculate_async(self, materials: list[MaterialData], lifecycle_stages: list[LifecycleStage] | None = None, progress: Callable[[int, int], None] | None = None) -> list[CarbonResult]
Asynchronously calculate embodied carbon with optional progress callback (completed, total).
EpdDatabase
Environmental Product Declaration database with local cache, generic fallback values, and optional EC3 API integration.
Module: revitpy.sustainability.epd
class EpdDatabase:
def __init__(self, *, api_token: str | None = None, cache_path: Path | str | None = None) -> None
Methods:
def lookup(self, material_name: str, category: str | None = None) -> EpdRecord | None
Look up an EPD record for a material. Searches exact cache match, fuzzy keyword match, then category-based generic fallback.
async def lookup_async(self, material_name: str, category: str | None = None) -> EpdRecord | None
Asynchronously look up an EPD record, querying the EC3 API when a token is configured and local cache misses.
async def search_async(self, query: str, limit: int = 10) -> list[EpdRecord]
Search for EPD records matching a query. Searches local cache and optionally the EC3 API.
def get_generic_epd(self, material_category: str) -> EpdRecord | None
Get a generic EPD record for a material category (e.g. "Concrete", "Metals").
def load_cache(self, path: Path | str) -> None
Load cached EPD records from a JSON file.
def save_cache(self, path: Path | str) -> None
Save cached EPD records to a JSON file.
ComplianceChecker
Check building data against emissions compliance standards including NYC LL97, Boston BERDO, EU EPBD, and ASHRAE 90.1.
Module: revitpy.sustainability.compliance
class ComplianceChecker:
def __init__(self) -> None
Methods:
def check(self, standard: ComplianceStandard, building_data: dict) -> ComplianceResult
Check compliance against a specific standard. Dispatches to the standard-specific checker. Required keys in building_data vary by standard.
def check_ll97(self, building_data: dict) -> ComplianceResult
Check NYC Local Law 97 compliance. Requires area_sqft and annual_emissions_tco2e.
def check_berdo(self, building_data: dict) -> ComplianceResult
Check Boston BERDO compliance. Requires area_sqft and annual_emissions_kgco2e.
def check_epbd(self, building_data: dict) -> ComplianceResult
Check EU EPBD compliance. Requires area_m2 and primary_energy_kwh.
def check_ashrae(self, envelope_data: EnergyEnvelopeData) -> ComplianceResult
Check ASHRAE 90.1 envelope compliance (wall R-value, roof R-value, window U-value, glazing ratio) for climate zone 4A.
def get_recommendations(self, result: ComplianceResult) -> list[str]
Get improvement recommendations based on a compliance result.
SustainabilityReporter
Generate sustainability assessment reports in JSON, CSV, and HTML formats, and produce certification documentation for LEED, BREEAM, DGNB, and Green Star.
Module: revitpy.sustainability.reports
class SustainabilityReporter:
def __init__(self) -> None
Methods:
def generate(self, summary: BuildingCarbonSummary, format: ReportFormat = ReportFormat.JSON, output_path: str | Path | None = None) -> str | Path
Generate a sustainability report. Returns content as a string when output_path is None, or the output Path when written to disk.
def to_json(self, summary: BuildingCarbonSummary, path: str | Path | None = None) -> str | Path
Generate a JSON sustainability report.
def to_csv(self, summary: BuildingCarbonSummary, path: str | Path | None = None) -> str | Path
Generate a CSV sustainability report with material rows, carbon values, and percentages.
def to_html(self, summary: BuildingCarbonSummary, path: str | Path | None = None) -> str | Path
Generate an HTML sustainability report. Uses Jinja2 if available, otherwise falls back to string formatting.
def generate_certification_docs(self, summary: BuildingCarbonSummary, system: CertificationSystem) -> dict
Generate certification documentation helpers for a given rating system (LEED, BREEAM, DGNB, Green Star). Returns a dict with certification-specific credit sections.
Speckle Interop (revitpy.interop)
SpeckleTypeMapper
Bidirectional mapping between RevitPy element types and Speckle object types, with custom property maps and type registration.
Module: revitpy.interop.mapper
class SpeckleTypeMapper:
def __init__(self) -> None
Properties:
| Property | Type | Description |
|---|---|---|
registered_types |
list[str] |
All registered RevitPy type names |
registered_speckle_types |
list[str] |
All registered Speckle type identifiers |
Methods:
def register_mapping(self, revitpy_type: str, speckle_type: str, property_map: dict[str, str] | None = None) -> None
Register a custom mapping between a RevitPy type and Speckle type.
def get_mapping(self, revitpy_type: str) -> TypeMapping | None
Get the Speckle mapping for a RevitPy type.
def to_speckle(self, element: Any) -> dict[str, Any]
Convert a RevitPy element to a Speckle-compatible dict. Raises TypeMappingError if the element type is not mapped.
def from_speckle(self, speckle_obj: dict[str, Any], target_type: str | None = None) -> dict[str, Any]
Convert a Speckle object dict back to a RevitPy-compatible dict. Consults the reverse registry when target_type is not provided.
def get_unmapped_status(self, revitpy_type: str) -> TypeMapping
Return a TypeMapping with MappingStatus.UNMAPPED for an unregistered type.
SpeckleClient
Async HTTP client for the Speckle GraphQL API. Uses httpx.AsyncClient for transport and optionally leverages specklepy.
Module: revitpy.interop.client
class SpeckleClient:
def __init__(self, config: SpeckleConfig | None = None) -> None
Properties:
| Property | Type | Description |
|---|---|---|
is_connected |
bool |
Whether the client has successfully connected |
config |
SpeckleConfig |
The current server configuration |
Methods:
async def connect(self) -> None
Validate the connection to the Speckle server by sending a serverInfo query.
async def get_streams(self) -> list[dict[str, Any]]
Return a list of streams visible to the authenticated user.
async def get_stream(self, stream_id: str) -> dict[str, Any]
Return details of a single stream.
async def get_branches(self, stream_id: str) -> list[dict[str, Any]]
Return the branches of a stream.
async def get_commits(self, stream_id: str, branch: str = "main", limit: int = 10) -> list[SpeckleCommit]
Return recent commits on a branch.
async def send_objects(self, stream_id: str, objects: list[dict[str, Any]], branch: str = "main", message: str = "") -> SpeckleCommit
Send objects to a Speckle stream and create a commit.
async def receive_objects(self, stream_id: str, commit_id: str | None = None, branch: str = "main") -> list[dict[str, Any]]
Receive objects from a Speckle stream. Uses the latest commit when commit_id is None.
async def close(self) -> None
Close the underlying HTTP client.
SpeckleSync
High-level synchronisation between RevitPy and Speckle, with push, pull, and bidirectional sync operations.
Module: revitpy.interop.sync
class SpeckleSync:
def __init__(self, client: SpeckleClient, mapper: SpeckleTypeMapper | None = None, change_tracker: Any | None = None) -> None
Methods:
async def push(self, elements: list[Any], stream_id: str, branch: str = "main", message: str = "") -> SyncResult
Push local elements to a Speckle stream. Maps each element via the mapper and sends through the client.
async def pull(self, stream_id: str, branch: str = "main", commit_id: str | None = None) -> list[dict[str, Any]]
Pull objects from a Speckle stream and map them back to RevitPy-compatible dicts.
async def sync(self, elements: list[Any], stream_id: str, mode: SyncMode = SyncMode.INCREMENTAL, direction: SyncDirection = SyncDirection.BIDIRECTIONAL) -> SyncResult
Run a full sync operation. Direction controls whether elements are pushed, pulled, or both. Mode controls whether all or only changed elements are synced.
SpeckleDiff
Compare local and remote element sets to produce diff entries describing additions, modifications, and removals at the property level.
Module: revitpy.interop.diff
class SpeckleDiff:
def __init__(self) -> None
Methods:
def compare(self, local_elements: list[dict[str, Any]], remote_elements: list[dict[str, Any]]) -> list[DiffEntry]
Compare local and remote element dicts and return diffs. Elements are matched by their id key.
def has_changes(self, local_elements: list[dict[str, Any]], remote_elements: list[dict[str, Any]]) -> bool
Return whether any differences exist between the two sets.
SpeckleMerge
Merge local and remote element sets according to a configurable conflict resolution strategy (LOCAL_WINS, REMOTE_WINS, or MANUAL).
Module: revitpy.interop.merge
class SpeckleMerge:
def __init__(self, resolution: ConflictResolution = ConflictResolution.LOCAL_WINS) -> None
Methods:
def merge(self, local_elements: list[dict[str, Any]], remote_elements: list[dict[str, Any]], diff_entries: list[DiffEntry] | None = None) -> MergeResult
Merge local and remote elements. Computes the diff automatically when diff_entries is None. Raises MergeConflictError when using MANUAL resolution with unresolved conflicts.
def resolve_conflicts(self, conflicts: list[DiffEntry], strategy: ConflictResolution) -> list[dict[str, Any]]
Resolve a list of conflict entries using the given strategy. Returns list of resolved property dicts.
Cloud & Design Automation (revitpy.cloud)
ApsAuthenticator
OAuth2 client-credentials authentication for Autodesk Platform Services, with token caching and automatic refresh.
Module: revitpy.cloud.auth
class ApsAuthenticator:
def __init__(self, credentials: ApsCredentials) -> None
Methods:
async def authenticate(self) -> ApsToken
Perform a fresh OAuth2 client-credentials authentication against the APS token endpoint.
async def get_token(self) -> ApsToken
Return a cached token, refreshing it if expired or not yet obtained.
def is_token_valid(self) -> bool
Check whether the cached token is still valid (uses a 60-second buffer before expiry).
ApsClient
Authenticated HTTP client for the APS API with sliding-window rate limiting (20 req/s) and exponential-backoff retry on transient failures.
Module: revitpy.cloud.client
class ApsClient:
def __init__(self, authenticator: ApsAuthenticator, *, region: CloudRegion = CloudRegion.US) -> None
Methods:
async def request(self, method: str, endpoint: str, **kwargs: Any) -> dict
Make an authenticated HTTP request with retry and rate limiting. Automatically injects Bearer token.
async def get(self, endpoint: str, **kwargs: Any) -> dict
Perform an authenticated GET request.
async def post(self, endpoint: str, **kwargs: Any) -> dict
Perform an authenticated POST request.
async def delete(self, endpoint: str, **kwargs: Any) -> dict
Perform an authenticated DELETE request.
JobManager
Manages Design Automation work items through the APS API: submit, poll, download results, cancel, and retrieve logs.
Module: revitpy.cloud.jobs
class JobManager:
def __init__(self, client: ApsClient) -> None
Methods:
async def submit(self, config: JobConfig) -> str
Submit a new Design Automation work item. Returns the job_id.
async def get_status(self, job_id: str) -> JobStatus
Get the current status of a work item.
async def wait_for_completion(self, job_id: str, timeout: float = 600.0, poll_interval: float = 5.0) -> JobResult
Poll a work item until it reaches a terminal state. Raises JobExecutionError on failure or timeout.
async def download_results(self, job_id: str, output_dir: Path) -> list[Path]
Download output files for a completed work item to a local directory.
async def cancel(self, job_id: str) -> bool
Cancel a running work item. Returns True if cancellation succeeded.
async def get_logs(self, job_id: str) -> str
Retrieve execution logs for a work item.
BatchProcessor
Process multiple Design Automation jobs concurrently with bounded parallelism, automatic retry, and optional progress/cancellation callbacks.
Module: revitpy.cloud.batch
class BatchProcessor:
def __init__(self, job_manager: JobManager, *, config: BatchConfig | None = None) -> None
Methods:
async def process(self, jobs: list[JobConfig], progress: Callable[[int, int], Any] | None = None, cancel: asyncio.Event | None = None) -> BatchResult
Process a list of jobs with bounded concurrency. Reports progress via callback (completed, total). Stops submitting new jobs when the cancel event is set.
async def process_directory(self, input_dir: Path, script_path: Path, *, activity_id: str = "RevitPy.Validate+prod", **kwargs: Any) -> BatchResult
Create and process jobs for every .rvt file in a directory.
CIHelper
Generate CI/CD pipeline configurations for GitHub Actions and GitLab CI.
Module: revitpy.cloud.ci
class CIHelper:
def __init__(self) -> None
Methods:
def generate_github_workflow(self, name: str = "revitpy-validation", script_path: str = "validate.py", revit_version: str = "2024", *, branches: str = "main", runner: str = "ubuntu-latest", python_version: str = "3.11") -> str
Generate a GitHub Actions workflow YAML string.
def generate_gitlab_ci(self, name: str = "revitpy-validation", script_path: str = "validate.py", revit_version: str = "2024", *, python_version: str = "3.11") -> str
Generate a GitLab CI pipeline YAML string.
def save_workflow(self, content: str, output_path: str | Path) -> Path
Write a workflow/pipeline configuration to disk.
WebhookHandler
Receive, verify (HMAC-SHA256), and route APS Design Automation webhook events to registered callbacks.
Module: revitpy.cloud.webhooks
class WebhookHandler:
def __init__(self, config: WebhookConfig | None = None) -> None
Methods:
def verify_signature(self, payload: bytes, signature: str) -> bool
Verify HMAC-SHA256 signature of an incoming webhook payload. Raises WebhookError if no secret is configured.
def handle_event(self, event_data: dict[str, Any]) -> WebhookEvent
Parse an incoming webhook payload and dispatch to registered callbacks. Returns the parsed WebhookEvent.
def register_callback(self, event_type: str, callback: Callable) -> None
Register a callback for a specific event type. Use "*" to listen for all event types.