demo ready

This commit is contained in:
Jonathon Broughton
2023-11-13 12:22:09 +00:00
parent 1f230df1e8
commit f077320638
6 changed files with 91 additions and 50 deletions
-1
View File
@@ -1 +0,0 @@
SPECKLE_TOKEN=mytoken
+6 -5
View File
@@ -95,7 +95,7 @@ class BaseObjectRules:
"""
return (
lambda parameter: getattr(parameter, "name") is not None
and parameter.name == parameter_name
and parameter.name == parameter_name
)
@staticmethod
@@ -116,12 +116,13 @@ class BaseObjectRules:
has a 'category' property.
"""
return (
getattr(parameter, "speckle_type", None)
== "Objects.BuiltElements.Revit.Parameter"
getattr(parameter, "speckle_type", None)
== "Objects.BuiltElements.Revit.Parameter"
)
@staticmethod
def evaluate_parameter(parameter, function_inputs):
"""Evaluates a parameter and returns its evaluation state."""
if not BaseObjectRules.is_revit_parameter(parameter):
return None
@@ -130,7 +131,7 @@ class BaseObjectRules:
return "missing"
value = getattr(parameter, "value", None)
if value is not None and value.startswith(function_inputs.single_rule):
return "valid"
if value is not None and isinstance(value, str) and value.startswith(function_inputs.single_rule):
return "passing"
else:
return "invalid"
+32
View File
@@ -0,0 +1,32 @@
from Rules.checks import BaseObjectRules
# Function to get type and family based on conditions
def get_type_and_family(obj):
if getattr(obj, "speckle_type", None) == "Objects.Other.Revit.RevitInstance" and hasattr(obj, "definition"):
return getattr(obj.definition, "type", "Unknown"), getattr(obj.definition, "family", "Unknown")
return getattr(obj, "type", "Unknown"), getattr(obj, "family", "Unknown")
# Function to create object info
def create_object_info(obj, type_, family):
return {
"name": getattr(obj, "name", "Unknown"),
"type": type_,
"family": family,
"id": getattr(obj, "id", "Unknown"),
}
# Function to process parameters
def process_parameters(current_object, function_inputs):
parameters = getattr(current_object, "parameters", None)
if not parameters:
return
parameter_name_is = BaseObjectRules.parameter_name_is(function_inputs.single_property)
for parameter_key in getattr(parameters, 'get_dynamic_member_names', lambda: [])():
parameter = parameters[parameter_key]
if parameter_name_is(parameter):
return BaseObjectRules.evaluate_parameter(parameter, function_inputs)
+34 -39
View File
@@ -14,6 +14,7 @@ from speckle_automate import (
from Rules.checks import BaseObjectRules
from Rules.traversal import get_data_traversal_rules
from Utilities.helpers import process_parameters, get_type_and_family, create_object_info
from Utilities.report import generate_report
@@ -108,8 +109,8 @@ class FunctionInputs(AutomateBase):
def automate_function(
automate_context: AutomationContext,
function_inputs: FunctionInputs,
automate_context: AutomationContext,
function_inputs: FunctionInputs,
) -> None:
"""
The core logic of the Speckle Automate function.
@@ -129,37 +130,17 @@ def automate_function(
# Assuming each object has properties: name, type, and id
assessed_objects = {"missing": [], "invalid": [], "passing": []}
# Checking parameters
# Main loop for checking parameters
for context in traversal_contexts_collection:
current_object = getattr(context.current, "parameters", None)
current_object = context.current
is_category = BaseObjectRules.is_category(function_inputs.single_category)
if current_object:
for parameter_key in current_object.get_dynamic_member_names():
parameter = current_object[parameter_key]
assessment = BaseObjectRules.evaluate_parameter(
parameter, function_inputs
)
if getattr(
current_object, "speckle_type", None
) == "Objects.Other.Revit.RevitInstance" and hasattr(
current_object, "definition"
):
type_ = getattr(current_object.definition, "type", "Unknown")
family = getattr(current_object.definition, "family", "Unknown")
else:
type_ = getattr(current_object, "type", "Unknown")
family = getattr(current_object, "family", "Unknown")
object_info = {
"name": getattr(current_object, "name", "Unknown"),
"type": type_,
"family": family,
"id": getattr(current_object, "id", "Unknown"),
}
if assessment:
assessed_objects[assessment].append(object_info)
if is_category(current_object) and hasattr(current_object, "parameters"):
assessment = process_parameters(current_object, function_inputs)
if assessment:
type_, family = get_type_and_family(current_object)
object_info = create_object_info(current_object, type_, family)
assessed_objects[assessment].append(object_info)
# Attach errors or info to objects based on their parameter evaluation state
for state, objects in assessed_objects.items():
@@ -176,8 +157,8 @@ def automate_function(
# Combine messages into a single string
combined_message = (
f"Found {len(objects)} objects with {state} parameters: "
+ "; ".join(detailed_messages)
f"Found {len(objects)} objects with {state} parameters: "
+ "; ".join(detailed_messages)
)
if state in ["missing", "invalid"]:
@@ -189,12 +170,6 @@ def automate_function(
category=state.capitalize(), object_ids=ids, message=combined_message
)
# Determine overall automation success or failure
if assessed_objects["missing"] or assessed_objects["invalid"]:
automate_context.mark_run_failed("Automation failed due to parameter issues.")
else:
automate_context.mark_run_success("All parameters are valid.")
# Generate and attach the report
report_format = (
function_inputs.report_format.value
@@ -208,6 +183,26 @@ def automate_function(
)
automate_context.store_file_result(report_file)
print("Report file: ", report_file)
# Determine overall automation success or failure
if assessed_objects["missing"] or assessed_objects["invalid"]:
total_objects = len(assessed_objects["missing"]) + len(assessed_objects["invalid"]) + len(
assessed_objects["passing"])
pass_rate = len(assessed_objects["passing"]) / total_objects * 100
invalid_rate = len(assessed_objects["invalid"]) / total_objects * 100
missing_rate = len(assessed_objects["missing"]) / total_objects * 100
success_rating_message = f"Pass rate: {pass_rate:.2f}%, Invalid rate: {invalid_rate:.2f}%, Missing rate: {missing_rate:.2f}%"
print(success_rating_message)
automate_context.mark_run_failed("Automation failed due to parameter issues. " + success_rating_message)
else:
automate_context.mark_run_success("All parameters are valid.")
# make sure to call the function with the executor
if __name__ == "__main__":
+19 -5
View File
@@ -100,8 +100,8 @@ def fake_automation_run_data(request, test_client: SpeckleClient) -> AutomationR
SERVER_URL = request.config.SPECKLE_SERVER_URL
TOKEN = request.config.SPECKLE_TOKEN
project_id = "9c6bfd2177"
model_id = "6193bdb540"
project_id = "4f064f09e6"
model_id = "180a044971"
function_name = "Automate Density Check"
@@ -122,7 +122,7 @@ def fake_automation_run_data(request, test_client: SpeckleClient) -> AutomationR
project_id=project_id,
model_id=model_id,
branch_name="main",
version_id="107527ebd2",
version_id="2729513a2d",
speckle_server_url=SERVER_URL,
# These ids would be available with a valid registered Automation definition.
automation_id=automation_id,
@@ -137,14 +137,28 @@ def fake_automation_run_data(request, test_client: SpeckleClient) -> AutomationR
return fake_run_data
def test_function_run(fake_automation_run_data: AutomationRunData, speckle_token: str):
def test_function_run_fail(fake_automation_run_data: AutomationRunData, speckle_token: str):
"""Run an integration test for the automate function."""
context = AutomationContext.initialize(fake_automation_run_data, speckle_token)
automate_sdk = run_function(
context,
automate_function,
FunctionInputs(density_level=1000, max_percentage_high_density_objects=0.1),
FunctionInputs(single_category="Windows", single_property="OmniClass Number", single_rule="23.30.20.00",
report_format="JSON")
)
assert automate_sdk.run_status == AutomationStatus.FAILED
def test_function_run_pass(fake_automation_run_data: AutomationRunData, speckle_token: str):
"""Run an integration test for the automate function."""
context = AutomationContext.initialize(fake_automation_run_data, speckle_token)
automate_sdk = run_function(
context,
automate_function,
FunctionInputs(single_category="Windows", single_property="OmniClass Number", single_rule="23.30.20")
)
assert automate_sdk.run_status != AutomationStatus.FAILED