Skip to content

Commit d71d452

Browse files
committed
Refactor computation function imports to use the new decorator module
1 parent 47b088f commit d71d452

File tree

17 files changed

+161
-159
lines changed

17 files changed

+161
-159
lines changed

sigima/proc/__init__.py

Lines changed: 0 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -104,143 +104,3 @@
104104
.. autofunction:: sigima.proc.get_computation_metadata
105105
.. autofunction:: sigima.proc.find_computation_functions
106106
"""
107-
108-
from __future__ import annotations
109-
110-
import dataclasses
111-
import functools
112-
import importlib
113-
import inspect
114-
import os.path as osp
115-
import pkgutil
116-
import sys
117-
from types import ModuleType
118-
from typing import Callable, Optional, TypeVar
119-
120-
if sys.version_info >= (3, 10):
121-
# Use ParamSpec from typing module in Python 3.10+
122-
from typing import ParamSpec
123-
else:
124-
# Use ParamSpec from typing_extensions module in Python < 3.10
125-
from typing_extensions import ParamSpec
126-
127-
# Marker attribute used by @computation_function and introspection
128-
COMPUTATION_METADATA_ATTR = "__computation_function_metadata"
129-
130-
P = ParamSpec("P")
131-
R = TypeVar("R")
132-
133-
134-
@dataclasses.dataclass(frozen=True)
135-
class ComputationMetadata:
136-
"""Metadata for a computation function.
137-
138-
Attributes:
139-
name: The name of the computation function.
140-
description: A description or docstring for the computation function.
141-
"""
142-
143-
name: str
144-
description: str
145-
146-
147-
def computation_function(
148-
*,
149-
name: Optional[str] = None,
150-
description: Optional[str] = None,
151-
) -> Callable[[Callable[P, R]], Callable[P, R]]:
152-
"""Decorator to mark a function as a Sigima computation function.
153-
154-
Args:
155-
name: Optional name to override the function name.
156-
description: Optional docstring override or additional description.
157-
158-
Returns:
159-
The wrapped function, tagged with a marker attribute.
160-
"""
161-
162-
def decorator(f: Callable[P, R]) -> Callable[P, R]:
163-
"""Decorator to mark a function as a Sigima computation function.
164-
This decorator adds a marker attribute to the function, allowing
165-
it to be identified as a computation function.
166-
It also allows for optional name and description overrides.
167-
The function can be used as a decorator or as a standalone function.
168-
"""
169-
170-
@functools.wraps(f)
171-
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
172-
return f(*args, **kwargs)
173-
174-
metadata = ComputationMetadata(
175-
name=name or f.__name__, description=description or f.__doc__
176-
)
177-
setattr(wrapper, COMPUTATION_METADATA_ATTR, metadata)
178-
return wrapper
179-
180-
return decorator
181-
182-
183-
def is_computation_function(function: Callable) -> bool:
184-
"""Check if a function is a Sigima computation function.
185-
186-
Args:
187-
function: The function to check.
188-
189-
Returns:
190-
True if the function is a Sigima computation function, False otherwise.
191-
"""
192-
return getattr(function, COMPUTATION_METADATA_ATTR, None) is not None
193-
194-
195-
def get_computation_metadata(function: Callable) -> ComputationMetadata:
196-
"""Get the metadata of a Sigima computation function.
197-
198-
Args:
199-
function: The function to get metadata from.
200-
201-
Returns:
202-
Computation function metadata.
203-
204-
Raises:
205-
ValueError: If the function is not a Sigima computation function.
206-
"""
207-
metadata = getattr(function, COMPUTATION_METADATA_ATTR, None)
208-
if not isinstance(metadata, ComputationMetadata):
209-
raise ValueError(
210-
f"The function {function.__name__} is not a Sigima computation function."
211-
)
212-
return metadata
213-
214-
215-
def find_computation_functions(
216-
module: ModuleType | None = None,
217-
) -> list[tuple[str, Callable]]:
218-
"""Find all computation functions in the `sigima.proc` package.
219-
220-
This function uses introspection to locate all functions decorated with
221-
`@computation_function` in the `sigima.proc` package and its subpackages.
222-
223-
Args:
224-
module: Optional module to search in. If None, the current module is used.
225-
226-
Returns:
227-
A list of tuples, each containing the function name and the function object.
228-
"""
229-
functions = []
230-
if module is None:
231-
path = [osp.dirname(__file__)]
232-
else:
233-
path = module.__path__
234-
objs = []
235-
for _, modname, _ in pkgutil.walk_packages(path=path, prefix=__name__ + "."):
236-
try:
237-
module = importlib.import_module(modname)
238-
except Exception: # pylint: disable=broad-except
239-
continue
240-
for name, obj in inspect.getmembers(module, inspect.isfunction):
241-
if is_computation_function(obj):
242-
if obj in objs: # Avoid double entries for the same function
243-
continue
244-
objs.append(obj)
245-
functions.append((modname, name, obj.__doc__))
246-
return functions

sigima/proc/decorator.py

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2+
3+
"""
4+
.. Computation function decorator and utilities
5+
(see parent package :mod:`sigima.computation`)
6+
"""
7+
8+
from __future__ import annotations
9+
10+
import dataclasses
11+
import functools
12+
import importlib
13+
import inspect
14+
import os.path as osp
15+
import pkgutil
16+
import sys
17+
from types import ModuleType
18+
from typing import Callable, Optional, TypeVar
19+
20+
if sys.version_info >= (3, 10):
21+
# Use ParamSpec from typing module in Python 3.10+
22+
from typing import ParamSpec
23+
else:
24+
# Use ParamSpec from typing_extensions module in Python < 3.10
25+
from typing_extensions import ParamSpec
26+
27+
# Marker attribute used by @computation_function and introspection
28+
COMPUTATION_METADATA_ATTR = "__computation_function_metadata"
29+
30+
P = ParamSpec("P")
31+
R = TypeVar("R")
32+
33+
34+
@dataclasses.dataclass(frozen=True)
35+
class ComputationMetadata:
36+
"""Metadata for a computation function.
37+
38+
Attributes:
39+
name: The name of the computation function.
40+
description: A description or docstring for the computation function.
41+
"""
42+
43+
name: str
44+
description: str
45+
46+
47+
def computation_function(
48+
*,
49+
name: Optional[str] = None,
50+
description: Optional[str] = None,
51+
) -> Callable[[Callable[P, R]], Callable[P, R]]:
52+
"""Decorator to mark a function as a Sigima computation function.
53+
54+
Args:
55+
name: Optional name to override the function name.
56+
description: Optional docstring override or additional description.
57+
58+
Returns:
59+
The wrapped function, tagged with a marker attribute.
60+
"""
61+
62+
def decorator(f: Callable[P, R]) -> Callable[P, R]:
63+
"""Decorator to mark a function as a Sigima computation function.
64+
This decorator adds a marker attribute to the function, allowing
65+
it to be identified as a computation function.
66+
It also allows for optional name and description overrides.
67+
The function can be used as a decorator or as a standalone function.
68+
"""
69+
70+
@functools.wraps(f)
71+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
72+
return f(*args, **kwargs)
73+
74+
metadata = ComputationMetadata(
75+
name=name or f.__name__, description=description or f.__doc__
76+
)
77+
setattr(wrapper, COMPUTATION_METADATA_ATTR, metadata)
78+
return wrapper
79+
80+
return decorator
81+
82+
83+
def is_computation_function(function: Callable) -> bool:
84+
"""Check if a function is a Sigima computation function.
85+
86+
Args:
87+
function: The function to check.
88+
89+
Returns:
90+
True if the function is a Sigima computation function, False otherwise.
91+
"""
92+
return getattr(function, COMPUTATION_METADATA_ATTR, None) is not None
93+
94+
95+
def get_computation_metadata(function: Callable) -> ComputationMetadata:
96+
"""Get the metadata of a Sigima computation function.
97+
98+
Args:
99+
function: The function to get metadata from.
100+
101+
Returns:
102+
Computation function metadata.
103+
104+
Raises:
105+
ValueError: If the function is not a Sigima computation function.
106+
"""
107+
metadata = getattr(function, COMPUTATION_METADATA_ATTR, None)
108+
if not isinstance(metadata, ComputationMetadata):
109+
raise ValueError(
110+
f"The function {function.__name__} is not a Sigima computation function."
111+
)
112+
return metadata
113+
114+
115+
def find_computation_functions(
116+
module: ModuleType | None = None,
117+
) -> list[tuple[str, Callable]]:
118+
"""Find all computation functions in the `sigima.proc` package.
119+
120+
This function uses introspection to locate all functions decorated with
121+
`@computation_function` in the `sigima.proc` package and its subpackages.
122+
123+
Args:
124+
module: Optional module to search in. If None, the current module is used.
125+
126+
Returns:
127+
A list of tuples, each containing the function name and the function object.
128+
"""
129+
functions = []
130+
if module is None:
131+
path = [osp.dirname(__file__)]
132+
else:
133+
path = module.__path__
134+
objs = []
135+
for _, modname, _ in pkgutil.walk_packages(path=path, prefix=__name__ + "."):
136+
try:
137+
module = importlib.import_module(modname)
138+
except Exception: # pylint: disable=broad-except
139+
continue
140+
for name, obj in inspect.getmembers(module, inspect.isfunction):
141+
if is_computation_function(obj):
142+
if obj in objs: # Avoid double entries for the same function
143+
continue
144+
objs.append(obj)
145+
functions.append((modname, name, obj.__doc__))
146+
return functions

sigima/proc/image/arithmetic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@
3434

3535
from sigima.config import options
3636
from sigima.objects.image import ImageObj
37-
from sigima.proc import computation_function
3837
from sigima.proc.base import (
3938
ArithmeticParam,
4039
ConstantParam,
4140
dst_1_to_1,
4241
dst_2_to_1,
4342
dst_n_to_1,
4443
)
44+
from sigima.proc.decorator import computation_function
4545
from sigima.proc.image.base import restore_data_outside_roi
4646
from sigima.tools.datatypes import clip_astype
4747

sigima/proc/image/detection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from sigima.config import _
3131
from sigima.objects.base import ResultShape, ShapeTypes
3232
from sigima.objects.image import ImageObj, create_image_roi
33-
from sigima.proc import computation_function
33+
from sigima.proc.decorator import computation_function
3434
from sigima.proc.image.base import calc_resultshape
3535

3636

sigima/proc/image/edges.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232

3333
from sigima.config import _
3434
from sigima.objects.image import ImageObj
35-
from sigima.proc import computation_function
3635
from sigima.proc.base import dst_1_to_1
36+
from sigima.proc.decorator import computation_function
3737
from sigima.proc.image.base import Wrap1to1Func, restore_data_outside_roi
3838

3939

sigima/proc/image/exposure.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
from sigima.objects.base import BaseProcParam
3636
from sigima.objects.image import ImageObj, ROI2DParam
3737
from sigima.objects.signal import SignalObj
38-
from sigima.proc import computation_function
3938
from sigima.proc.base import (
4039
ClipParam,
4140
HistogramParam,
@@ -44,6 +43,7 @@
4443
dst_2_to_1,
4544
new_signal_result,
4645
)
46+
from sigima.proc.decorator import computation_function
4747
from sigima.proc.image.base import Wrap1to1Func, restore_data_outside_roi
4848

4949

sigima/proc/image/extraction.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
from sigima.config import _
3535
from sigima.objects.image import ImageObj, ImageROI, ROI2DParam
3636
from sigima.objects.signal import SignalObj
37-
from sigima.proc import computation_function
3837
from sigima.proc.base import dst_1_to_1
38+
from sigima.proc.decorator import computation_function
3939
from sigima.proc.image.base import dst_1_to_1_signal
4040

4141

sigima/proc/image/filtering.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@
3232

3333
from sigima.config import _
3434
from sigima.objects.image import ImageObj
35-
from sigima.proc import computation_function
3635
from sigima.proc.base import (
3736
GaussianParam,
3837
MovingAverageParam,
3938
MovingMedianParam,
4039
dst_1_to_1,
4140
)
41+
from sigima.proc.decorator import computation_function
4242
from sigima.proc.image.base import Wrap1to1Func, restore_data_outside_roi
4343
from sigima.tools.image import freq_fft_filter
4444

sigima/proc/image/fourier.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
import sigima.tools.image as alg
3434
from sigima.config import _
3535
from sigima.objects.image import ImageObj
36-
from sigima.proc import computation_function
3736
from sigima.proc.base import FFTParam, SpectrumParam, dst_1_to_1
37+
from sigima.proc.decorator import computation_function
3838
from sigima.proc.image.base import Wrap1to1Func
3939

4040

sigima/proc/image/geometry.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
import sigima.tools.image as alg
3535
from sigima.config import _
3636
from sigima.objects.image import ImageObj
37-
from sigima.proc import computation_function
3837
from sigima.proc.base import dst_1_to_1
38+
from sigima.proc.decorator import computation_function
3939
from sigima.proc.image.base import Wrap1to1Func
4040
from sigima.tools.coordinates import vector_rotation
4141

0 commit comments

Comments
 (0)