Compare commits
5 Commits
is_set_rule
...
1.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 129132dd3a | |||
| f902f9c23f | |||
| 7158d0576d | |||
| bb87a7b932 | |||
| f1c4e65d72 |
@@ -44,3 +44,4 @@ jobs:
|
||||
speckle_function_id: ${{ secrets.SPECKLE_FUNCTION_ID }}
|
||||
speckle_function_input_schema_file_path: ${{ env.FUNCTION_SCHEMA_FILE_NAME }}
|
||||
speckle_function_command: 'python -u main.py run'
|
||||
speckle_function_recommended_memory_mi: 5000
|
||||
|
||||
Generated
+3
@@ -4,4 +4,7 @@
|
||||
<option name="sdkName" value="WSL Checker" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="uv (Checker)" project-jdk-type="Python SDK" />
|
||||
<component name="PythonCompatibilityInspectionAdvertiser">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -18,19 +18,19 @@ The Checker function allows you to:
|
||||
|
||||
### 1. Prepare Your Rule Spreadsheet
|
||||
|
||||
1. Access the [template spreadsheet](https://docs.google.com/spreadsheets/d/1hiPSw23eOaqd27QD_YsXvZg9PWm7_XBx/edit) (
|
||||
make a copy to your drive)
|
||||
2. Define your rules using the format explained below
|
||||
3. Publish your rules by clicking "File > Download > Tab-separated values (.tsv)"
|
||||
4. Upload the TSV file to a hosting service (Google Drive, Dropbox, etc.) and get a public URL
|
||||
1. Access
|
||||
the [template spreadsheet](https://docs.google.com/spreadsheets/d/1eB0RVuOXdjLyn4_GAPSahV05p1lqfSGQbH8WWijnkkA/edit?gid=0#gid=0)
|
||||
2. Use the Speckle menu to launch the Speckle sidebar and make a copy.
|
||||
3. Define your rules using the format explained below
|
||||
4. Publish your rules by clicking "Publish Rules". Copy the resultant URL.
|
||||
|
||||
### 2. Create an Automation
|
||||
|
||||
1. Go to [Speckle Automate](https://automate.speckle.dev/)
|
||||
1. Go to your workspace project in [Speckle](https://app.speckle.systems/)
|
||||
2. Create a new Automation
|
||||
3. Select the Checker function
|
||||
4. Configure the function:
|
||||
- Paste your TSV URL
|
||||
- Paste your published rules URL
|
||||
- Set minimum severity level to report
|
||||
- Configure other options as needed
|
||||
5. Save and run your automation
|
||||
@@ -58,20 +58,20 @@ Rules are defined in a spreadsheet with the following columns:
|
||||
|
||||
### Supported Predicates
|
||||
|
||||
| Predicate | Description | Example |
|
||||
|------------------|-----------------------------|------------------------------------|
|
||||
| exists | Checks if a property exists | `height` exists |
|
||||
| equal to | Exact value match | `width` equal to `300` |
|
||||
| not equal to | Value doesn't match | `material` not equal to `Concrete` |
|
||||
| greater than | Value exceeds threshold | `height` greater than `3000` |
|
||||
| less than | Value below threshold | `thickness` less than `50` |
|
||||
| in range | Value within bounds | `elevation` in range `0,10000` |
|
||||
| in list | Value in allowed set | `type` in list `W1,W2,W3` |
|
||||
| contains | Property contains substring | `name` contains `Beam` |
|
||||
| does not contain | Property doesn't contain | `name` does not contain `temp` |
|
||||
| is true | Boolean property is true | `is_structural` is true |
|
||||
| is false | Boolean property is false | `is_placeholder` is false |
|
||||
| is like | Pattern matching | `name` is like `^BR\d+$` |
|
||||
| Predicate | Description | Example |
|
||||
|------------------|-----------------------------|---------------------------------------|
|
||||
| exists | Checks if a property exists | `height` exists |
|
||||
| equal to | Exact value match | `width` equal to `300` |
|
||||
| not equal to | Value doesn't match | `material` not equal to `Concrete` |
|
||||
| greater than | Value exceeds threshold | `height` greater than `3000` |
|
||||
| less than | Value below threshold | `thickness` less than `50` |
|
||||
| in range | Value within bounds | `elevation` in range `0,10000` |
|
||||
| in list | Value in allowed set | `type` in list `W1,W2,W3` |
|
||||
| contains | Property contains substring | `name` contains `Beam` |
|
||||
| does not contain | Property doesn't contain | `name` does not contain `temp` |
|
||||
| is true | Boolean property is true | `is_structural` is true |
|
||||
| is false | Boolean property is false | `is_placeholder` is false |
|
||||
| is like | Loose text matching | `name` is like `Wall` matches `Walls` |
|
||||
|
||||
## Rule Logic
|
||||
|
||||
@@ -118,4 +118,4 @@ Severity: ERROR
|
||||
|
||||
## Support
|
||||
|
||||
For issues or questions, please open a GitHub issue or contact your Speckle support representative.
|
||||
For issues or questions, please let us know on the [Speckle Community Forum](https://speckle.community/).
|
||||
|
||||
+12
-6
@@ -95,7 +95,7 @@ def evaluate_condition(
|
||||
Returns:
|
||||
True if the condition is met, False otherwise
|
||||
"""
|
||||
property_name = condition["Property Name"]
|
||||
property_name = condition.get("Property Name", condition.get("Property Path"))
|
||||
predicate_key = condition["Predicate"]
|
||||
value = condition["Value"]
|
||||
|
||||
@@ -263,21 +263,27 @@ def apply_rules_to_objects(
|
||||
rules_processed += 1
|
||||
|
||||
# Ensure rule_group has necessary columns
|
||||
if "Message" not in rule_group.columns or "Report Severity" not in rule_group.columns:
|
||||
if "Message" not in rule_group.columns or (
|
||||
"Report Severity" not in rule_group.columns and "Severity" not in rule_group.columns
|
||||
):
|
||||
continue # Or raise an exception if these columns are mandatory
|
||||
|
||||
pass_objects, fail_objects = process_rule(speckle_objects, rule_group)
|
||||
|
||||
# Get the severity level for this rule
|
||||
rule_severity = get_severity(rule_group.iloc[-1])
|
||||
rule_severity_level = severity_levels[MinimumSeverity(rule_severity.value)]
|
||||
|
||||
# Check if the rule severity level meets the minimum severity level - no point in processing lower severity rules
|
||||
if rule_severity_level < min_severity_level:
|
||||
continue
|
||||
|
||||
pass_objects, fail_objects = process_rule(speckle_objects, rule_group)
|
||||
|
||||
# For passing objects, only attach if we're showing all levels (INFO)
|
||||
if minimum_severity == MinimumSeverity.INFO:
|
||||
attach_results(pass_objects, rule_group.iloc[-1], rule_id_str, automate_context, True)
|
||||
|
||||
# For failing objects, attach if they meet minimum severity threshold
|
||||
if rule_severity_level >= min_severity_level:
|
||||
if len(fail_objects) and rule_severity_level >= min_severity_level:
|
||||
attach_results(fail_objects, rule_group.iloc[-1], rule_id_str, automate_context, False)
|
||||
|
||||
if len(pass_objects) == 0 and len(fail_objects) == 0 and not hide_skipped:
|
||||
@@ -323,7 +329,7 @@ def get_severity(rule_info: pd.Series) -> SeverityLevel:
|
||||
Returns:
|
||||
Appropriate SeverityLevel enum value
|
||||
"""
|
||||
severity = rule_info.get("Report Severity") # Extract severity from input data
|
||||
severity = rule_info.get("Report Severity") or rule_info.get("Severity") # Extract severity from input data
|
||||
|
||||
# If severity is None or not a string (e.g., numeric input), default to ERROR
|
||||
if not isinstance(severity, str):
|
||||
|
||||
+6
-6
@@ -64,8 +64,10 @@ def process_rule_numbers(df: DataFrame) -> DataFrame:
|
||||
# Get slice of rows for this group
|
||||
group_slice = df.iloc[start_idx:end_idx]
|
||||
|
||||
# Try to get rule number from first row
|
||||
group_rule_num = group_slice["Rule Number"].iloc[0]
|
||||
# Try to get rule number from first row, fall back to "Rule #"
|
||||
group_rule_num = (
|
||||
group_slice["Rule Number"].iloc[0] if not pd.isna(group_slice["Rule Number"].iloc[0]) else "Rule #"
|
||||
)
|
||||
|
||||
if pd.isna(group_rule_num):
|
||||
# If no rule number, generate next available number
|
||||
@@ -90,8 +92,7 @@ def process_rule_numbers(df: DataFrame) -> DataFrame:
|
||||
|
||||
|
||||
def validate_rule_numbers(df: DataFrame) -> list[str]:
|
||||
""" "
|
||||
Validate rule numbers and return any warnings or errors.
|
||||
"""Validate rule numbers and return any warnings or errors.
|
||||
|
||||
This checks for issues like:
|
||||
1. Missing rule numbers
|
||||
@@ -128,8 +129,7 @@ def validate_rule_numbers(df: DataFrame) -> list[str]:
|
||||
|
||||
|
||||
def read_rules_from_spreadsheet(url: str) -> tuple[DataFrameGroupBy, list[str]] | tuple[None, list[str]]:
|
||||
""" "
|
||||
Reads rules from a TSV file at the provided URL, processes them, and returns grouped rules.
|
||||
"""Reads rules from a TSV file at the provided URL, processes them, and returns grouped rules.
|
||||
|
||||
This function is the main entry point for rule loading:
|
||||
1. Reads the TSV file from the provided URL
|
||||
|
||||
@@ -30,12 +30,14 @@ class TestFunction:
|
||||
|
||||
"""Run an integration test for the automate function."""
|
||||
automation_context = AutomationContext.initialize(test_automation_run_data, test_automation_token)
|
||||
default_url: str = "https://drive.google.com/uc?export=download&id=1hiPSw23eOaqd27QD_YsXvZg9PWm7_XBx"
|
||||
default_url: str = (
|
||||
"https://speckle-model-checker-cedxvz7lzq-ew.a.run.app/r/6hdycwPELyTIT7Ueedh0UsWdJlTBefwSjDlcnd8LXGg/tsv"
|
||||
)
|
||||
|
||||
automate_sdk = run_function(
|
||||
automation_context,
|
||||
automate_function,
|
||||
FunctionInputs(spreadsheet_url=default_url, minimum_severity=MinimumSeverity.WARNING, hide_skipped=True),
|
||||
FunctionInputs(spreadsheet_url=default_url, minimum_severity=MinimumSeverity.INFO, hide_skipped=True),
|
||||
)
|
||||
|
||||
assert automate_sdk.run_status == AutomationStatus.SUCCEEDED
|
||||
|
||||
Reference in New Issue
Block a user