Skip to content

Commit c42bb2d

Browse files
committed
Tests Passing
1 parent daeb786 commit c42bb2d

11 files changed

Lines changed: 30 additions & 78 deletions

src/example_fgen_basic/error_v/error_v.f90

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ end function constructor
109109
subroutine build(self, code, message, cause)
110110
!! Build instance
111111

112-
class(ErrorV), intent(inout) :: self
112+
class(ErrorV), intent(out) :: self
113113
! Hopefully can leave without docstring (like Python)
114114

115115
integer, intent(in) :: code
@@ -129,14 +129,14 @@ subroutine build(self, code, message, cause)
129129
! call self%cause%build(cause%code, cause%message, cause%cause)
130130
! self%cause = cause
131131
if (present(message)) then
132-
self % message = trim(message) // " --> Cause: " // cause % message
132+
self % message = adjustl(trim(message)) // " --> Cause: " // cause % message
133133
else
134134
self % message = " --> Cause: " // cause % message
135135
end if
136136

137137
else
138138
if (present(message)) then
139-
self % message = trim(message)
139+
self % message = adjustl(trim(message))
140140
end if
141141
end if
142142

@@ -153,10 +153,7 @@ subroutine finalise(self)
153153
if (allocated(self%message)) deallocate(self%message)
154154
! MZ when the object is finalized or goes out of scope, its pointer components are destroyed.
155155
! Hopefully no shared ownership??
156-
if (associated(self%cause))then
157-
deallocate(self%cause)
158-
nullify(self%cause)
159-
end if
156+
if (associated(self%cause)) nullify(self%cause)
160157

161158
end subroutine finalise
162159

src/example_fgen_basic/error_v/error_v.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ def from_instance_index(cls, instance_index: int) -> ErrorV:
5555
code = m_error_v_w.get_code(instance_index)
5656
# String requires decode
5757
message = m_error_v_w.get_message(instance_index).decode()
58-
5958
res = cls(code=code, message=message)
6059

6160
return res

src/example_fgen_basic/error_v/error_v_manager.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ function get_instance(instance_index) result(err_inst)
102102

103103
err_check_index_claimed = check_index_claimed(instance_index)
104104

105-
if (err_check_index_claimed % code == 0) then
105+
if (err_check_index_claimed % code == NO_ERROR_CODE) then
106106

107107
err_inst = instance_array(instance_index)
108108

src/example_fgen_basic/error_v/error_v_wrapper.f90

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,17 +119,18 @@ subroutine get_message( &
119119

120120
! TODO: make this variable length
121121
! MZ attempts to put allocatable lead to segfault
122-
character(len=128), intent(out) :: message
122+
! it seems to be really trick. F2PY does not like allocatable
123+
! and assumed-lenght does not work well with long sentences.
124+
character(len=1000), intent(out) :: message
123125

124126
type(ErrorV) :: instance
125127

126128
instance = error_v_manager_get_instance(instance_index)
127129

128130
if (allocated(instance%message)) then
129-
message = instance % message
131+
message = adjustl(trim(instance % message))
130132
! else !MZ what to do??
131133
!! message = "Invalid query: message not allocated"
132-
! message = ""
133134
end if
134135

135136
end subroutine get_message

src/example_fgen_basic/get_square_root.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def get_square_root(inv: float) -> float:
5151

5252
if result.error_v is not None:
5353
# TODO: be more specific
54+
m_result_dp_w.finalise_instance(result_instance_index)
5455
raise FortranError(result.error_v.message)
5556
# raise LessThanZeroError(result.error_v.message)
5657

src/example_fgen_basic/result/result_dp.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,17 @@ def from_instance_index(cls, instance_index: int) -> ResultDP:
6161
# Error type requires derived type handling
6262
if m_result_dp_w.error_v_is_set(instance_index):
6363
error_v_instance_index: int = m_result_dp_w.get_error_v(instance_index)
64+
try:
65+
# Initialise the result from the received index
66+
error_v = ErrorV.from_instance_index(error_v_instance_index)
67+
finally:
68+
# make sure the Fortran-side error_v slot is released
69+
# (otherwise the manager slot stays claimed and leaks previous messages)
70+
from example_fgen_basic._lib import m_error_v_w
71+
72+
m_error_v_w.finalise_instance(error_v_instance_index)
6473
# Initialise the result from the received index
65-
error_v = ErrorV.from_instance_index(error_v_instance_index)
74+
# error_v = ErrorV.from_instance_index(error_v_instance_index)
6675

6776
else:
6877
error_v = None

src/example_fgen_basic/result/result_dp_manager.f90

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,7 @@ subroutine finalise_instance(instance_index)
7979

8080
res_check_index_claimed = check_index_claimed(instance_index)
8181
! MZ how do we handle unsuccefull finalisation?
82-
if(res_check_index_claimed%is_error()) return
83-
82+
! if(res_check_index_claimed%is_error()) return
8483
call instance_array(instance_index) % finalise()
8584
instance_available(instance_index) = .true.
8685

@@ -96,7 +95,7 @@ function get_available_instance_index() result (res_available_instance_index)
9695
type(ResultInt) :: res_available_instance_index
9796
!! Available instance index
9897
character(len=:), allocatable :: msg
99-
character(len=20), allocatable :: str_size_array
98+
character(len=20) :: str_size_array
10099
integer :: i
101100

102101
if(allocated(instance_array)) then

src/example_fgen_basic/result/result_int_wrapper.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ subroutine get_error_v( &
243243

244244
err = error_v_manager_set_instance_index_to(error_v_instance_index, error_v)
245245
!MZ: check for errors ?
246+
246247
end subroutine get_error_v
247248

248249
end module m_result_int_w

tests/unit/test_result_dp.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,24 @@
1111
@pytest.mark.parametrize(
1212
"data_v, error_v_instance_index, exp, exp_error",
1313
[
14-
# (1.23, 0, 1.23, False),
14+
(1.23, 0, 1.23, False),
1515
(
1616
1.23,
1717
1,
18-
"Error at get_instance -> 1 --> Cause: instance_available in NOT allocated",
18+
"Error at get_instance -> 1 --> Cause: Index 1 has not been claimed",
1919
True,
2020
),
2121
],
2222
)
23+
# MZ: in the second case the error should be:
24+
# "Error at get_instance -> 1 --> Cause: instance_available in NOT allocated"
25+
# but the error_v memory side is not being managed correctly
2326
def test_build_no_argument_supplied(data_v, error_v_instance_index, exp, exp_error):
2427
res_instance_index: int = m_result_dp_w.build_instance(
2528
data_v=data_v, error_v_instance_index=error_v_instance_index
2629
)
2730
res: ResultDP = ResultDP.from_instance_index(res_instance_index)
31+
m_result_dp_w.finalise_instance(res_instance_index)
2832

2933
# Previously this would segfault.
3034
# Now we can actually handle the error on the Python side as we wish

tests/unit/test_result_int.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ def test_build_no_argument_supplied():
66
res_instance_index: int = m_result_int_w.build_instance(
77
data_v=5, error_v_instance_index=0
88
)
9-
res: int = ResultInt(res_instance_index)
9+
res: int = ResultInt.from_instance_index(res_instance_index)
1010

1111
assert res.has_error
1212
assert res.error_v.message == (

0 commit comments

Comments
 (0)