• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pomponchik / transfunctions / 16452616546

22 Jul 2025 06:34PM UTC coverage: 97.321% (+0.2%) from 97.17%
16452616546

push

github

web-flow
Merge pull request #5 from pomponchik/develop

0.0.5

30 of 31 new or added lines in 2 files covered. (96.77%)

218 of 224 relevant lines covered (97.32%)

5.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.31
/transfunctions/decorators/superfunction.py
1
import sys
6✔
2
import weakref
6✔
3
from ast import NodeTransformer, Return, AST
6✔
4
from inspect import currentframe
6✔
5
from functools import wraps
6✔
6
from typing import Dict, Any, Optional, Union, List, Callable
6✔
7
from collections.abc import Coroutine
6✔
8

9
if sys.version_info <= (3, 10):  # pragma: no cover
10
    from typing_extensions import TypeAlias
11
else:  # pragma: no cover
12
    from typing import TypeAlias
13

14
from displayhooks import not_display
6✔
15

16
from transfunctions.transformer import FunctionTransformer
6✔
17
from transfunctions.errors import WrongTransfunctionSyntaxError
6✔
18

19

20
if sys.version_info <= (3, 9):  # pragma: no cover
21
    CoroutineClass = Coroutine
22
else:  # pragma: no cover
23
    CoroutineClass: TypeAlias = Coroutine[Any, Any, None]
24

25
class UsageTracer(CoroutineClass):
6✔
26
    def __init__(self, args, kwargs, transformer, tilde_syntax: bool) -> None:
6✔
27
        self.flags: Dict[str, bool] = {}
6✔
28
        self.args = args
6✔
29
        self.kwargs = kwargs
6✔
30
        self.transformer = transformer
6✔
31
        self.tilde_syntax = tilde_syntax
6✔
32
        self.coroutine = self.async_option(self.flags, args, kwargs, transformer)
6✔
33
        self.finalizer = weakref.finalize(self, self.sync_option, self.flags, args, kwargs, transformer, self.coroutine, tilde_syntax)
6✔
34

35
    def __iter__(self):
6✔
36
        self.flags['used'] = True
6✔
37
        self.coroutine.close()
6✔
38
        generator_function = self.transformer.get_generator_function()
6✔
39
        generator = generator_function(*(self.args), **(self.kwargs))
6✔
40
        yield from generator
6✔
41

42
    def __await__(self) -> Any:  # pragma: no cover
43
        return self.coroutine.__await__()
44

45
    def __invert__(self):
6✔
46
        if not self.tilde_syntax:
6✔
47
            raise NotImplementedError('The syntax with ~ is disabled for this superfunction. Call it with simple breackets.')
6✔
48

49
        self.flags['used'] = True
6✔
50
        self.coroutine.close()
6✔
51
        return self.transformer.get_usual_function()(*(self.args), **(self.kwargs))
6✔
52

53
    def send(self, value: Any) -> Any:
6✔
54
        return self.coroutine.send(value)
6✔
55

56
    def throw(self, exception_type: Any, value: Any = None, traceback: Any = None) -> None:  # pragma: no cover
57
        pass
58

59
    def close(self) -> None:  # pragma: no cover
60
        pass
61

62
    @staticmethod
6✔
63
    def sync_option(flags: Dict[str, bool], args, kwargs, transformer, wrapped_coroutine: CoroutineClass, tilde_syntax: bool) -> None:
6✔
64
        if not flags.get('used', False):
6✔
65
            wrapped_coroutine.close()
6✔
66
            if not tilde_syntax:
6✔
67
                return transformer.get_usual_function()(*args, **kwargs)
6✔
68
            else:
69
                raise NotImplementedError(f'The tilde-syntax is enabled for the "{transformer.function.__name__}" function. Call it like this: ~{transformer.function.__name__}().')
6✔
70

71
    @staticmethod
6✔
72
    async def async_option(flags: Dict[str, bool], args, kwargs, transformer) -> None:
6✔
73
        flags['used'] = True
6✔
74
        return await transformer.get_async_function()(*args, **kwargs)
6✔
75

76

77
not_display(UsageTracer)
6✔
78

79
def superfunction(*args: Callable, tilde_syntax: bool = True):
6✔
80
    def decorator(function):
6✔
81
        class NoReturns(NodeTransformer):
6✔
82
            def visit_Return(self, node: Return) -> Optional[Union[AST, List[AST]]]:
6✔
NEW
83
                raise WrongTransfunctionSyntaxError('A superfunction cannot contain a return statement.')
×
84

85
        transformer = FunctionTransformer(
6✔
86
            function,
87
            currentframe().f_back.f_lineno,
88
            'superfunction',
89
            extra_transformers=[
90
                #NoReturns(),
91
            ],
92
        )
93

94
        @wraps(function)
6✔
95
        def wrapper(*args, **kwargs):
6✔
96
            return UsageTracer(args, kwargs, transformer, tilde_syntax)
6✔
97

98
        wrapper.__is_superfunction__ = True
6✔
99

100
        return wrapper
6✔
101

102
    if args:
6✔
103
        return decorator(args[0])
6✔
104
    return decorator
6✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc