mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 14:23:53 +00:00
fix(selector): round() should not crash on non-numeric values (#6776)
FormatTransformer.round() called Decimal() directly on the input value, which raises decimal.InvalidOperation when the value is a non-numeric string (a text property, or a value carrying a unit suffix like "12.5 m"). In a spreadsheet export this crashed the entire operation as soon as one element carried such a value. Now round() catches InvalidOperation and returns the value unchanged, the same graceful-fallback convention used by add(). Numeric rounding is unaffected. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
Dion Moult
parent
6b3cc54afc
commit
2eea7728d2
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
from decimal import Decimal
|
from decimal import Decimal, InvalidOperation
|
||||||
from types import EllipsisType
|
from types import EllipsisType
|
||||||
from typing import Any, Optional, Union
|
from typing import Any, Optional, Union
|
||||||
|
|
||||||
@@ -316,7 +316,13 @@ class FormatTransformer(lark.Transformer):
|
|||||||
return value in ("true", "1", "yes")
|
return value in ("true", "1", "yes")
|
||||||
|
|
||||||
def round(self, args):
|
def round(self, args):
|
||||||
value = Decimal(0.0 if args[0] == "None" else args[0] or 0.0)
|
try:
|
||||||
|
value = Decimal(0.0 if args[0] == "None" else args[0] or 0.0)
|
||||||
|
except InvalidOperation:
|
||||||
|
# The value is not numeric (e.g. a text property, or a value with
|
||||||
|
# a unit suffix like "12.5 m"). Rounding is meaningless here, so
|
||||||
|
# return it unchanged instead of crashing the whole expression.
|
||||||
|
return args[0]
|
||||||
nearest = Decimal(args[1])
|
nearest = Decimal(args[1])
|
||||||
result = round(value / nearest) * nearest
|
result = round(value / nearest) * nearest
|
||||||
if nearest % 1 == 0:
|
if nearest % 1 == 0:
|
||||||
|
|||||||
@@ -55,6 +55,9 @@ class TestFormat(test.bootstrap.IFC4):
|
|||||||
assert subject.format("round(123, 5)") == "125"
|
assert subject.format("round(123, 5)") == "125"
|
||||||
assert subject.format('round("123", 5)') == "125"
|
assert subject.format('round("123", 5)') == "125"
|
||||||
assert subject.format("round(-123, 5)") == "-125"
|
assert subject.format("round(-123, 5)") == "-125"
|
||||||
|
# Non-numeric values must pass through unchanged instead of crashing (#6776).
|
||||||
|
assert subject.format('round("Level 1", 0.01)') == "Level 1"
|
||||||
|
assert subject.format('round("12.5 m", 0.01)') == "12.5 m"
|
||||||
assert subject.format("int(123.123)") == "123"
|
assert subject.format("int(123.123)") == "123"
|
||||||
assert subject.format("int(123)") == "123"
|
assert subject.format("int(123)") == "123"
|
||||||
assert subject.format("number(123)") == "123"
|
assert subject.format("number(123)") == "123"
|
||||||
|
|||||||
Reference in New Issue
Block a user