-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathisa.py
167 lines (110 loc) · 3.82 KB
/
isa.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
"""constants to define the execution state for a notebook document.
## note
all of the doctests are scoped for a `doctest` invocation
>>> import isa
>>> assert isa.MODULE and not (isa.SCRIPT or isa.INTERACTIVE)
>>> assert isa.MODULE and isa.FILE and not isa.MAIN
"""
from abc import ABCMeta
from functools import wraps
from inspect import currentframe, getouterframes
__all__ = "MAIN", "FILE", "INTERACTIVE", "SCRIPT", "MODULE"
def get_last_module():
"""the execution is determined for module calling a method
inside classes and functions the local and global scopes are different.
we walk the outer frames until we discovered the module where the
frame is referenced. it is best to use this method in the top level of a module.
"""
for frame in getouterframes(currentframe()):
if frame.frame.f_locals is frame.frame.f_globals:
return frame.frame
def _default_globals(callable):
@wraps(callable)
def default(globals=None):
if globals is None:
globals = get_last_module().f_globals
return callable(globals)
return default
# the state __name__ and __file__ are our primary conditions for execution state
@_default_globals
def is_main(globals=None):
"""determine if the globals name is main
>>> assert not is_main()"""
return globals.get("__name__") == "__main__"
@_default_globals
def is_file(globals=None):
"""determine if the globals contain a source file name
>>> assert is_file()"""
return bool(globals.get("__file__"))
@_default_globals
def is_interactive(globals=None):
"""determine if the globals are running as an interactive notebook
>>> assert not is_interactive()"""
return is_main(globals) and not is_file(globals)
@_default_globals
def is_module(globals=None):
"""determine if the globals are running as an imported module
>>> assert is_module()"""
return not is_main(globals) and is_file(globals)
@_default_globals
def is_script(globals=None):
"""determine if the globals are running from a command line script
>>> assert not is_script()"""
return is_main(globals) and is_file(globals)
class State(ABCMeta):
"""base type for execution state flags"""
def __bool__(cls, level=1):
return cls.predicate(get_last_module().f_globals)
def __str__(cls):
return str(bool(cls))
def __or__(a, b):
return a or b
def __ror__(b, a):
return a or b
def __and__(a, b):
return a and b
def __rand__(b, a):
return b and a
class MAIN(metaclass=State):
""">>> assert not MAIN"""
@classmethod
def predicate(cls, globals):
return is_main(globals)
class FILE(metaclass=State):
""">>> assert FILE"""
@classmethod
def predicate(cls, globals):
return bool(is_file(globals))
# the execution states are secondary combinations of __name__ and __file__ states
class INTERACTIVE(metaclass=State):
""">>> assert not INTERACTIVE"""
@classmethod
def predicate(cls, globals):
return is_interactive(globals)
class SCRIPT(metaclass=State):
""">>> assert not SCRIPT"""
@classmethod
def predicate(cls, globals):
return is_script(globals)
class MODULE(metaclass=State):
""">>> assert MODULE"""
@classmethod
def predicate(cls, globals):
return is_module(globals)
if SCRIPT:
print(
f"""interactive: {INTERACTIVE}
module: {MODULE}
script: {SCRIPT}"""
)
elif MODULE:
from subprocess import check_output
__test__ = dict(
test_script=f""">>> print(check_output(["python", "{__file__}"]).decode().rstrip())
interactive: False
module: False
script: True""",
test_higher_conditons=""">>> assert not (MAIN | SCRIPT)
>>> assert not MAIN & (not SCRIPT) & (not MAIN)
>>> assert MODULE & (not MAIN) & FILE """,
)