Skip to content

Commit cb9d7cd

Browse files
committed
Fix rune_resolve_attr to resolve not only the local variables, but also the function parameters. First simple function example.
1 parent ac796cd commit cb9d7cd

File tree

6 files changed

+94
-4
lines changed

6 files changed

+94
-4
lines changed

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ dependencies = [
1212
"tzdata>=2025.2"
1313
]
1414
optional-dependencies.dev = [
15-
"pytest>=8.4.1",
16-
"pytest-cov>=6.2.1",
15+
"pytest>=9.0.2",
16+
"pytest-cov>=7.0.0",
1717
"pytest-mock>=3.14.1",
1818
"types-python-dateutil>=2.9.0.20250809"
1919
]

src/rune/runtime/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ def rune_resolve_attr(obj: Any | None, attrib: str) -> Any | list[Any] | None:
6969
attrib = rune_mangle_name(attrib)
7070

7171
if inspect.isframe(obj):
72-
obj = getattr(obj, 'f_locals')
72+
return obj.f_locals.get(attrib)
7373
elif isinstance(obj, dict):
74-
return obj[attrib]
74+
return obj.get(attrib)
7575

7676
return getattr(obj, attrib, None)
7777

test/__init__.py

Whitespace-only changes.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# pylint: disable=line-too-long, invalid-name, missing-function-docstring, missing-module-docstring, superfluous-parens
2+
# pylint: disable=wrong-import-position, unused-import, unused-wildcard-import, wildcard-import, wrong-import-order, missing-class-docstring
3+
from __future__ import annotations
4+
import sys
5+
import inspect
6+
from decimal import Decimal
7+
from pydantic import validate_call
8+
from rune.runtime.utils import rune_all_elements, rune_resolve_attr
9+
from rune.runtime.conditions import rune_execute_local_conditions, rune_local_condition
10+
from rune.runtime.func_proxy import replaceable, create_module_attr_guardian
11+
from .RoundingModeEnum import RoundingModeEnum
12+
13+
__all__ = ['RoundToNearest']
14+
15+
16+
@replaceable
17+
@validate_call
18+
def RoundToNearest(value: Decimal, nearest: Decimal, roundingMode: RoundingModeEnum) -> Decimal:
19+
"""
20+
Round a number to the supplied nearest, using the supplied rounding mode.
21+
22+
Parameters
23+
----------
24+
value : number
25+
The original (unrounded) number.
26+
27+
nearest : number
28+
The nearest number to round to.
29+
30+
roundingMode : RoundingModeEnum
31+
The method of rounding (up to nearest/down to nearest).
32+
33+
Returns
34+
-------
35+
roundedValue : number
36+
37+
"""
38+
_pre_registry = {}
39+
self = inspect.currentframe()
40+
41+
# conditions
42+
43+
@rune_local_condition(_pre_registry)
44+
def condition_0_PositiveNearest(): #FIXME: here we should NOT generate cond_name(self) as it is a closure function
45+
return rune_all_elements(rune_resolve_attr(self, "nearest"), ">", 0)
46+
# Execute all registered conditions
47+
rune_execute_local_conditions(_pre_registry, 'Pre-condition') #FIXME: the generator needs to add the rine_ prefix
48+
49+
roundedValue = Decimal(round(value, int(nearest)))
50+
51+
52+
return roundedValue
53+
54+
sys.modules[__name__].__class__ = create_module_attr_guardian(sys.modules[__name__].__class__)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# pylint: disable=missing-module-docstring, invalid-name, line-too-long
2+
from enum import Enum
3+
import rune.runtime.metadata
4+
5+
__all__ = ['RoundingModeEnum']
6+
7+
class RoundingModeEnum(rune.runtime.metadata.EnumWithMetaMixin, Enum):
8+
"""
9+
The enumerated values to specify the rounding direction when rounding of a number to nearest. Used by function cdm.base.math.RoundToNearest.
10+
"""
11+
DOWN = "Down"
12+
"""
13+
A number will be rounded down to the specified nearest number. For example, 529 rounded down to the nearest 10 is 520.
14+
"""
15+
UP = "Up"
16+
"""
17+
A number will be rounded up to the specified nearest number. For example, 521 rounded up to the nearest 10 is 530.
18+
"""
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from decimal import Decimal
2+
import pytest
3+
from pydantic import ValidationError
4+
from test.functions.specs.RoundToNearest import RoundToNearest
5+
from test.functions.specs.RoundingModeEnum import RoundingModeEnum
6+
7+
8+
def test_simple_types():
9+
x = RoundToNearest(Decimal(4.59989), Decimal(1), RoundingModeEnum.UP)
10+
assert x == Decimal('4.6')
11+
12+
with pytest.raises(ValidationError):
13+
x = RoundToNearest(
14+
'some text', # type: ignore
15+
Decimal(1),
16+
RoundingModeEnum.UP)
17+
18+
# EOF

0 commit comments

Comments
 (0)