Skip to content

Commit b3aa299

Browse files
committed
Get tests passing again
1 parent 63ed6b0 commit b3aa299

11 files changed

Lines changed: 104 additions & 481 deletions

File tree

Makefile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ test: ## run the tests (re-installs the package every time so you might want to
4949
# because it is looking for lines in `src` to be run,
5050
# but they're not because lines in `.venv` are run instead.
5151
# We don't have a solution to this yet.
52-
#
53-
# Coverage directory - needed to trick code cov to looking at the right place
52+
uv run --no-sync python scripts/inject-srcs-into-meson-build.py
5453
uv run --no-sync python -c 'from pathlib import Path; import example_fgen_basic' || ( echo "Run make virtual-environment first" && false )
5554
COV_DIR=$$(uv run --no-sync python -c 'from pathlib import Path; import example_fgen_basic; print(Path(example_fgen_basic.__file__).parent)'); \
5655
uv run --no-editable --reinstall-package example-fgen-basic pytest -r a -v tests src --doctest-modules --doctest-report ndiff --cov=$$COV_DIR

meson.build

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ if pyprojectwheelbuild_enabled
5252
# Injected with `script/inject-srcs-into-meson-build.py`
5353
srcs = files(
5454
'src/example_fgen_basic/error_v/creation_wrapper.f90',
55-
'src/example_fgen_basic/error_v/error_v_ptr_based_wrapper.f90',
5655
'src/example_fgen_basic/error_v/error_v_wrapper.f90',
5756
'src/example_fgen_basic/get_wavelength_wrapper.f90',
5857
)

src/example_fgen_basic/error_v/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
Definition of an error value
33
"""
44

5-
from example_fgen_basic.error_v.error_v import ErrorV, ErrorVPtrBased
5+
from example_fgen_basic.error_v.error_v import ErrorV
66

7-
__all__ = ["ErrorV", "ErrorVPtrBased"]
7+
__all__ = ["ErrorV"]

src/example_fgen_basic/error_v/creation.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from __future__ import annotations
66

7-
from example_fgen_basic.error_v.error_v import ErrorV, ErrorVPtrBased
7+
from example_fgen_basic.error_v.error_v import ErrorV
88
from example_fgen_basic.pyfgen_runtime.exceptions import CompiledExtensionNotFoundError
99

1010
try:
@@ -24,16 +24,3 @@ def create_error(inv: int) -> ErrorV:
2424
error = ErrorV(instance_index)
2525

2626
return error
27-
28-
29-
def create_error_ptr_based(inv: int) -> ErrorVPtrBased:
30-
"""
31-
Create an instance of error (a wrapper around our Fortran derived type)
32-
33-
Uses the pointer based logic
34-
"""
35-
instance_ptr = m_error_v_creation_w.create_error_ptr_based(inv)
36-
37-
error = ErrorVPtrBased(instance_ptr)
38-
39-
return error

src/example_fgen_basic/error_v/creation_wrapper.f90

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module m_error_v_creation_w
1919
implicit none
2020
private
2121

22-
public :: create_error, create_error_ptr_based
22+
public :: create_error
2323

2424
contains
2525

@@ -39,45 +39,22 @@ subroutine create_error(inv, res_instance_index)
3939

4040
type(ErrorV), pointer :: res
4141

42-
! Use the pointer more or less like a normal instance of the derived type
43-
res = o_create_error(inv)
44-
4542
! This is the other trick for wrapping.
4643
! We have to ensure that we have correctly associated pointers
4744
! with the derived type instances we want to 'pass' across the Python-Fortran interface.
4845
! Once we've done this, we can then set them more or less like normal derived types.
4946
res_instance_index = error_v_manager_get_free_instance_number()
47+
! We have to associate res with the right index
48+
! before we can set it to the output of the function call
49+
! (in this case `o_create_error`).
5050
call error_v_manager_associate_pointer_with_instance(res_instance_index, res)
51-
! Ensure that the instance index is set correctly
52-
res % instance_index = res_instance_index
53-
54-
end subroutine create_error
55-
56-
subroutine create_error_ptr_based(inv, res_instance_ptr)
57-
! Needs to be subroutine to have the created instance persist I think
58-
! (we can check)
59-
! function create_error(inv) result(res_instance_index)
6051

61-
integer, intent(in) :: inv
62-
!! Input value to use to create the error
63-
64-
!f2py integer(8), intent(out) :: res_instance_ptr
65-
type(c_ptr), intent(out) :: res_instance_ptr
66-
!! Pointer to the resulting instance
67-
!
68-
! This is the major trick for wrapping.
69-
! We return pointers (passed as integers) to Python rather than the instance itself.
70-
71-
type(ErrorV), pointer :: res
72-
73-
! Question is: when does this get deallocated?
74-
! When we go out of scope?
75-
! If yes, that will be why we had to do this array thing.
76-
allocate(res)
52+
! Use the pointer more or less like a normal instance of the derived type
7753
res = o_create_error(inv)
7854

79-
res_instance_ptr = c_loc(res)
55+
! Ensure that the instance index is set correctly
56+
res % instance_index = res_instance_index
8057

81-
end subroutine create_error_ptr_based
58+
end subroutine create_error
8259

8360
end module m_error_v_creation_w

src/example_fgen_basic/error_v/error_v.py

Lines changed: 16 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,13 @@
1010

1111
from example_fgen_basic.pyfgen_runtime.base_finalisable import (
1212
FinalisableWrapperBase,
13-
FinalisableWrapperBasePtrBased,
1413
check_initialised,
15-
check_initialised_ptr_based,
16-
execute_finalise_on_fail_ptr_based,
14+
execute_finalise_on_fail,
1715
)
1816
from example_fgen_basic.pyfgen_runtime.exceptions import CompiledExtensionNotFoundError
1917

2018
try:
2119
from example_fgen_basic._lib import ( # type: ignore
22-
m_error_v_ptr_based_w,
2320
m_error_v_w,
2421
)
2522
except (ModuleNotFoundError, ImportError) as exc: # pragma: no cover
@@ -48,77 +45,20 @@ def exposed_attributes(self) -> tuple[str, ...]:
4845
"""
4946
return ("code", "message")
5047

51-
# TODO: from_build_args, from_new_connection, context manager, finalise
52-
53-
@property
54-
@check_initialised
55-
def code(self) -> int:
56-
"""
57-
Error code
58-
59-
Returns
60-
-------
61-
:
62-
Error code, retrieved from Fortran
63-
"""
64-
code: int = m_error_v_w.iget_code(instance_index=self.instance_index)
65-
66-
return code
67-
68-
@property
69-
@check_initialised
70-
def message(self) -> str:
71-
"""
72-
Error message
73-
74-
Returns
75-
-------
76-
:
77-
Error message, retrieved from Fortran
78-
"""
79-
message: str = m_error_v_w.iget_message(
80-
instance_index=self.instance_index
81-
).decode()
82-
83-
return message
84-
85-
86-
@define
87-
class ErrorVPtrBased(FinalisableWrapperBasePtrBased):
88-
"""
89-
TODO: auto docstring e.g. "Wrapper around the Fortran :class:`ErrorV`"
90-
91-
Uses the pointer-based passing logic
92-
"""
93-
94-
# Bug in Ipython pretty hence have to put this on every object?
95-
def _repr_pretty_(self, p: Any, cycle: bool) -> None:
96-
"""
97-
Get pretty representation of self
98-
99-
Used by IPython notebooks and other tools
100-
"""
101-
super()._repr_pretty_(p=p, cycle=cycle)
102-
103-
@property
104-
def exposed_attributes(self) -> tuple[str, ...]:
105-
"""
106-
Attributes exposed by this wrapper
107-
"""
108-
return ("code", "message")
109-
48+
# TODO: context manager
11049
@classmethod
111-
def from_new_connection(cls) -> ErrorVPtrBased:
50+
def from_new_connection(cls) -> ErrorV:
11251
"""
11352
Initialise from a new connection
11453
11554
The user is responsible for releasing this connection
11655
using :attr:`~finalise` when it is no longer needed.
117-
Alternatively a :obj:`~AtmosphereToOceanCarbonFluxCalculatorContext`
56+
Alternatively an [ErrorVContext][]
11857
can be used to handle the finalisation using a context manager.
11958
12059
Returns
12160
-------
61+
:
12262
A new instance with a unique instance index
12363
12464
Raises
@@ -128,26 +68,24 @@ def from_new_connection(cls) -> ErrorVPtrBased:
12868
12969
This could occur if too many instances are allocated at any one time
13070
"""
131-
instance_ptr = m_error_v_ptr_based_w.get_instance_ptr()
132-
# TODO: result type handling here
71+
instance_ptr: int = m_error_v_w.get_free_instance_number()
13372

13473
return cls(instance_ptr)
13574

136-
# TODO: from_build_args, from_new_connection, context manager, finalise
13775
@classmethod
13876
def from_build_args(
13977
cls,
14078
code: int,
14179
message: str = "",
142-
) -> ErrorVPtrBased:
80+
) -> ErrorV:
14381
"""
14482
Build the class (including connecting to Fortran)
14583
"""
14684
out = cls.from_new_connection()
14785
# TODO: remove or update this construct when we have result types
148-
execute_finalise_on_fail_ptr_based(
86+
execute_finalise_on_fail(
14987
out,
150-
m_error_v_ptr_based_w.instance_build,
88+
m_error_v_w.instance_build,
15189
code=code,
15290
message=message,
15391
)
@@ -159,28 +97,11 @@ def finalise(self) -> None:
15997
"""
16098
Close the connection with the Fortran module
16199
"""
162-
m_error_v_ptr_based_w.instance_finalise(self.instance_ptr)
163-
self._uninitialise_instance_ptr()
164-
165-
@property
166-
def is_associated(self) -> bool:
167-
"""
168-
Check whether `self`'s pointer is associated on the Fortran side
169-
170-
Returns
171-
-------
172-
:
173-
Whether `self`'s pointer is associated on the Fortran side
174-
"""
175-
if self.instance_ptr is None:
176-
return False
177-
178-
res: bool = bool(m_error_v_ptr_based_w.is_associated(self.instance_ptr)) # type: ignore
179-
180-
return res
100+
m_error_v_w.instance_finalise(self.instance_index)
101+
self._uninitialise_instance_index()
181102

182103
@property
183-
@check_initialised_ptr_based
104+
@check_initialised
184105
def code(self) -> int:
185106
"""
186107
Error code
@@ -190,12 +111,12 @@ def code(self) -> int:
190111
:
191112
Error code, retrieved from Fortran
192113
"""
193-
code: int = m_error_v_ptr_based_w.iget_code(instance_ptr=self.instance_ptr)
114+
code: int = m_error_v_w.iget_code(instance_index=self.instance_index)
194115

195116
return code
196117

197118
@property
198-
@check_initialised_ptr_based
119+
@check_initialised
199120
def message(self) -> str:
200121
"""
201122
Error message
@@ -205,8 +126,8 @@ def message(self) -> str:
205126
:
206127
Error message, retrieved from Fortran
207128
"""
208-
message: str = m_error_v_ptr_based_w.iget_message(
209-
instance_ptr=self.instance_ptr
129+
message: str = m_error_v_w.iget_message(
130+
instance_index=self.instance_index
210131
).decode()
211132

212133
return message

0 commit comments

Comments
 (0)