sflkit 0.5.3__tar.gz → 0.5.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sflkit-0.5.3/src/sflkit.egg-info → sflkit-0.5.4}/PKG-INFO +1 -1
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/__init__.py +1 -1
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/factory.py +63 -22
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/meta.py +5 -2
- sflkit-0.5.4/src/sflkit/model/scope.py +82 -0
- {sflkit-0.5.3 → sflkit-0.5.4/src/sflkit.egg-info}/PKG-INFO +1 -1
- sflkit-0.5.4/tests/test_scope.py +43 -0
- sflkit-0.5.3/src/sflkit/model/scope.py +0 -39
- sflkit-0.5.3/tests/test_scope.py +0 -20
- {sflkit-0.5.3 → sflkit-0.5.4}/LICENSE +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/README.md +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/pyproject.toml +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/setup.cfg +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/analysis_type.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/analyzer.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/mapping.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/predicate.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/similarity.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/spectra.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/analysis/suggestion.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/cli.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/color.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/config.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/evaluation.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/events/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/events/event_file.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/events/mapping.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/features/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/features/handler.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/features/value.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/features/vector.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/instrumentation/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/instrumentation/dir_instrumentation.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/instrumentation/file_instrumentation.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/extract.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/finder.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/java/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/java/extract.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/java/factory.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/java/finder.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/java/visitor.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/language.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/python/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/python/extract.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/python/factory.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/python/finder.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/python/visitor.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/language/visitor.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/logger.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/model/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/model/model.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/model/parallel.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/runners/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/runners/run.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/weights/__init__.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/weights/analyzer.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit/weights/models.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit.egg-info/SOURCES.txt +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit.egg-info/dependency_links.txt +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit.egg-info/entry_points.txt +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit.egg-info/requires.txt +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/src/sflkit.egg-info/top_level.txt +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_analysis_objects.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_analyzer.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_cli.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_color.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_config.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_coverage.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_dependency_weights.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_evaluation.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_events.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_execution.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_features.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_instrumentation.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_language.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_parallelization.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_predicates.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_runner.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_runner_parallel.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_runner_pytest_versions.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_spectra.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_suggestions.py +0 -0
- {sflkit-0.5.3 → sflkit-0.5.4}/tests/test_visitors.py +0 -0
|
@@ -85,7 +85,7 @@ class LineFactory(AnalysisFactory):
|
|
|
85
85
|
if key not in self.objects:
|
|
86
86
|
self.objects[key] = Line(event)
|
|
87
87
|
return [self.objects[key]]
|
|
88
|
-
return
|
|
88
|
+
return []
|
|
89
89
|
|
|
90
90
|
|
|
91
91
|
class BranchFactory(AnalysisFactory):
|
|
@@ -117,7 +117,7 @@ class BranchFactory(AnalysisFactory):
|
|
|
117
117
|
return [self.objects[key], self.objects[else_key]]
|
|
118
118
|
return [self.objects[key]]
|
|
119
119
|
|
|
120
|
-
return
|
|
120
|
+
return []
|
|
121
121
|
|
|
122
122
|
|
|
123
123
|
class FunctionFactory(AnalysisFactory):
|
|
@@ -130,7 +130,7 @@ class FunctionFactory(AnalysisFactory):
|
|
|
130
130
|
if key not in self.objects:
|
|
131
131
|
self.objects[key] = Function(event)
|
|
132
132
|
return [self.objects[key]]
|
|
133
|
-
return
|
|
133
|
+
return []
|
|
134
134
|
|
|
135
135
|
|
|
136
136
|
class LoopFactory(AnalysisFactory):
|
|
@@ -170,27 +170,70 @@ class LoopFactory(AnalysisFactory):
|
|
|
170
170
|
elif event.event_type == EventType.LOOP_END:
|
|
171
171
|
return self.objects[key][:]
|
|
172
172
|
return list()
|
|
173
|
-
return
|
|
173
|
+
return []
|
|
174
174
|
|
|
175
175
|
|
|
176
176
|
class DefUseFactory(AnalysisFactory):
|
|
177
177
|
def __init__(self):
|
|
178
178
|
super().__init__()
|
|
179
179
|
self.id_to_def: dict[EventFile, dict[tuple[str, int], DefEvent]] = dict()
|
|
180
|
+
self.def_stack: dict[EventFile, dict[int, dict[tuple[str, int], DefEvent]]] = (
|
|
181
|
+
dict()
|
|
182
|
+
)
|
|
180
183
|
|
|
181
184
|
def reset(self, event_file: EventFile):
|
|
182
|
-
|
|
183
|
-
self.id_to_def[event_file]
|
|
185
|
+
if event_file in self.id_to_def:
|
|
186
|
+
del self.id_to_def[event_file]
|
|
187
|
+
if event_file in self.def_stack:
|
|
188
|
+
del self.def_stack[event_file]
|
|
189
|
+
|
|
190
|
+
def _find_def_event(
|
|
191
|
+
self,
|
|
192
|
+
event_file: EventFile,
|
|
193
|
+
scope_id: int,
|
|
194
|
+
var_name: str,
|
|
195
|
+
var_id: int,
|
|
196
|
+
) -> DefEvent:
|
|
197
|
+
# Strategy 1: Check in scope
|
|
198
|
+
def_event = None
|
|
199
|
+
if event_file in self.def_stack and scope_id in self.def_stack[event_file]:
|
|
200
|
+
def_event = self.def_stack[event_file][scope_id].get(
|
|
201
|
+
(var_name, var_id), None
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# Strategy 2: Look up in the global DEF stack (other threads)
|
|
205
|
+
if def_event is None:
|
|
206
|
+
if event_file in self.id_to_def:
|
|
207
|
+
def_event = self.id_to_def[event_file].get((var_name, var_id), None)
|
|
208
|
+
|
|
209
|
+
return def_event
|
|
184
210
|
|
|
185
211
|
def get_analysis(
|
|
186
212
|
self, event, event_file: EventFile, scope: Scope = None
|
|
187
213
|
) -> List[AnalysisObject]:
|
|
214
|
+
thread_id = event.thread_id
|
|
215
|
+
scope_id = scope.id if scope else 0
|
|
216
|
+
|
|
188
217
|
if event.event_type == EventType.DEF:
|
|
189
|
-
|
|
190
|
-
|
|
218
|
+
key = (event.var, event.var_id)
|
|
219
|
+
|
|
220
|
+
# Initialize structures if needed
|
|
221
|
+
if event_file not in self.id_to_def:
|
|
222
|
+
self.id_to_def[event_file] = dict()
|
|
223
|
+
if event_file not in self.def_stack:
|
|
224
|
+
self.def_stack[event_file] = dict()
|
|
225
|
+
if scope_id not in self.def_stack[event_file]:
|
|
226
|
+
self.def_stack[event_file][scope_id] = dict()
|
|
227
|
+
|
|
228
|
+
# Store the DEF event
|
|
229
|
+
self.id_to_def[event_file][key] = event
|
|
230
|
+
self.def_stack[event_file][scope_id][key] = event
|
|
231
|
+
|
|
191
232
|
elif event.event_type == EventType.USE:
|
|
192
|
-
|
|
193
|
-
|
|
233
|
+
def_event = self._find_def_event(
|
|
234
|
+
event_file, scope_id, event.var, event.var_id
|
|
235
|
+
)
|
|
236
|
+
|
|
194
237
|
if def_event:
|
|
195
238
|
key = (
|
|
196
239
|
DefUse.analysis_type(),
|
|
@@ -204,7 +247,7 @@ class DefUseFactory(AnalysisFactory):
|
|
|
204
247
|
if key not in self.objects:
|
|
205
248
|
self.objects[key] = DefUse(def_event, event)
|
|
206
249
|
return [self.objects[key]]
|
|
207
|
-
return
|
|
250
|
+
return []
|
|
208
251
|
|
|
209
252
|
|
|
210
253
|
class ConditionFactory(AnalysisFactory):
|
|
@@ -305,7 +348,7 @@ class ScalarPairFactory(ComparisonFactory):
|
|
|
305
348
|
)
|
|
306
349
|
objects.append(self.objects[key])
|
|
307
350
|
return objects
|
|
308
|
-
return
|
|
351
|
+
return []
|
|
309
352
|
|
|
310
353
|
|
|
311
354
|
class VariableFactory(ComparisonFactory):
|
|
@@ -332,7 +375,7 @@ class VariableFactory(ComparisonFactory):
|
|
|
332
375
|
self.objects[key] = VariablePredicate(event, comp)
|
|
333
376
|
objects.append(self.objects[key])
|
|
334
377
|
return objects
|
|
335
|
-
return
|
|
378
|
+
return []
|
|
336
379
|
|
|
337
380
|
|
|
338
381
|
class ReturnFactory(ComparisonFactory):
|
|
@@ -402,7 +445,7 @@ class ReturnFactory(ComparisonFactory):
|
|
|
402
445
|
)
|
|
403
446
|
objects.append(self.objects[key])
|
|
404
447
|
return objects
|
|
405
|
-
return
|
|
448
|
+
return []
|
|
406
449
|
|
|
407
450
|
|
|
408
451
|
class ConstantCompFactory(AnalysisFactory):
|
|
@@ -429,7 +472,7 @@ class ConstantCompFactory(AnalysisFactory):
|
|
|
429
472
|
self.objects[key] = self.class_(event)
|
|
430
473
|
objects.append(self.objects[key])
|
|
431
474
|
return objects
|
|
432
|
-
return
|
|
475
|
+
return []
|
|
433
476
|
|
|
434
477
|
|
|
435
478
|
class NoneFactory(ConstantCompFactory):
|
|
@@ -467,7 +510,7 @@ class PredicateFunctionFactory(AnalysisFactory):
|
|
|
467
510
|
# noinspection PyArgumentList
|
|
468
511
|
self.objects[key] = self.class_(event)
|
|
469
512
|
return [self.objects[key]]
|
|
470
|
-
return
|
|
513
|
+
return []
|
|
471
514
|
|
|
472
515
|
|
|
473
516
|
class IsAsciiFactory(PredicateFunctionFactory):
|
|
@@ -518,7 +561,7 @@ class LengthFactory(AnalysisFactory):
|
|
|
518
561
|
Length(event, Length.evaluate_length_more)
|
|
519
562
|
)
|
|
520
563
|
return self.objects[key][:]
|
|
521
|
-
return
|
|
564
|
+
return []
|
|
522
565
|
|
|
523
566
|
|
|
524
567
|
class FunctionErrorFactory(AnalysisFactory):
|
|
@@ -530,11 +573,9 @@ class FunctionErrorFactory(AnalysisFactory):
|
|
|
530
573
|
self, event, event_file: EventFile, scope: Scope = None
|
|
531
574
|
) -> List[AnalysisObject]:
|
|
532
575
|
if event.event_type == EventType.FUNCTION_ENTER:
|
|
533
|
-
|
|
534
|
-
self.function_mapping[event.function_id] = event.line
|
|
576
|
+
self.function_mapping[event.function_id] = event.line
|
|
535
577
|
if event.event_type in (EventType.FUNCTION_ERROR, EventType.FUNCTION_EXIT):
|
|
536
|
-
|
|
537
|
-
line = self.function_mapping.get(event.function_id, event.line)
|
|
578
|
+
line = self.function_mapping.get(event.function_id, event.line)
|
|
538
579
|
key = (
|
|
539
580
|
FunctionErrorPredicate.analysis_type(),
|
|
540
581
|
event.file,
|
|
@@ -547,7 +588,7 @@ class FunctionErrorFactory(AnalysisFactory):
|
|
|
547
588
|
event.file, line, event.function
|
|
548
589
|
)
|
|
549
590
|
return [self.objects[key]]
|
|
550
|
-
return
|
|
591
|
+
return []
|
|
551
592
|
|
|
552
593
|
|
|
553
594
|
analysis_factory_mapping = {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import random
|
|
2
2
|
from abc import ABC
|
|
3
|
+
from threading import Lock
|
|
3
4
|
from typing import List, Type, Any
|
|
4
5
|
|
|
5
6
|
from sflkitlib.events.event import Event
|
|
@@ -60,10 +61,12 @@ class Injection:
|
|
|
60
61
|
class IDGenerator:
|
|
61
62
|
def __init__(self):
|
|
62
63
|
self.current_id = 0
|
|
64
|
+
self.lock = Lock()
|
|
63
65
|
|
|
64
66
|
def get_next_id(self):
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
with self.lock:
|
|
68
|
+
id_ = self.current_id
|
|
69
|
+
self.current_id += 1
|
|
67
70
|
return id_
|
|
68
71
|
|
|
69
72
|
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from threading import Lock
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Var(object):
|
|
6
|
+
def __init__(self, var, value, type_, id_: int = None):
|
|
7
|
+
self.var = var
|
|
8
|
+
self.value = value
|
|
9
|
+
self.type_ = type_
|
|
10
|
+
self.id = id_ if id_ is not None else hash(self)
|
|
11
|
+
|
|
12
|
+
def __hash__(self):
|
|
13
|
+
return hash(self.var)
|
|
14
|
+
|
|
15
|
+
def __eq__(self, other):
|
|
16
|
+
return isinstance(other, Var) and self.var == other.var
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class IDGenerator:
|
|
20
|
+
def __init__(self):
|
|
21
|
+
self.current_id = 0
|
|
22
|
+
self.lock = Lock()
|
|
23
|
+
|
|
24
|
+
def get_next_id(self):
|
|
25
|
+
with self.lock:
|
|
26
|
+
self.current_id += 1
|
|
27
|
+
return self.current_id
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Scope(object):
|
|
31
|
+
|
|
32
|
+
SCOPE_ID = IDGenerator()
|
|
33
|
+
|
|
34
|
+
def __init__(self, parent=None):
|
|
35
|
+
self.parent = parent
|
|
36
|
+
self.variables = dict()
|
|
37
|
+
self.id = Scope.SCOPE_ID.get_next_id()
|
|
38
|
+
|
|
39
|
+
def __hash__(self):
|
|
40
|
+
return hash(self.id)
|
|
41
|
+
|
|
42
|
+
def __eq__(self, other):
|
|
43
|
+
return isinstance(other, Scope) and self.id == other.id
|
|
44
|
+
|
|
45
|
+
def enter(self):
|
|
46
|
+
return Scope(parent=self)
|
|
47
|
+
|
|
48
|
+
def exit(self):
|
|
49
|
+
if self.parent is not None:
|
|
50
|
+
return self.parent
|
|
51
|
+
else:
|
|
52
|
+
return self
|
|
53
|
+
|
|
54
|
+
def __contains__(self, var: str) -> bool:
|
|
55
|
+
current = self
|
|
56
|
+
while current is not None:
|
|
57
|
+
if var in current.variables:
|
|
58
|
+
return True
|
|
59
|
+
current = current.parent
|
|
60
|
+
return False
|
|
61
|
+
|
|
62
|
+
def value(self, var: str) -> Var:
|
|
63
|
+
current = self
|
|
64
|
+
while current is not None:
|
|
65
|
+
if var in current.variables:
|
|
66
|
+
return current.variables[var].value
|
|
67
|
+
current = current.parent
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
def add(self, var, value, type_, id_: int = None):
|
|
71
|
+
self.variables[var] = Var(var, value, type_, id_)
|
|
72
|
+
|
|
73
|
+
def get_all_vars_dict(self):
|
|
74
|
+
current = self
|
|
75
|
+
variables = dict()
|
|
76
|
+
while current is not None:
|
|
77
|
+
variables = {**current.variables, **variables}
|
|
78
|
+
current = current.parent
|
|
79
|
+
return variables
|
|
80
|
+
|
|
81
|
+
def get_all_vars(self) -> List[Var]:
|
|
82
|
+
return list(self.get_all_vars_dict().values())
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
from sflkit.model.scope import Var, Scope
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TestScope(unittest.TestCase):
|
|
7
|
+
def test_var_eq(self):
|
|
8
|
+
var_1 = Var("x", 2, int)
|
|
9
|
+
var_2 = Var("y", 2, int)
|
|
10
|
+
var_3 = Var("x", "", str)
|
|
11
|
+
self.assertEqual(var_1, var_3)
|
|
12
|
+
self.assertNotEqual(var_1, var_2)
|
|
13
|
+
self.assertNotEqual(var_2, var_3)
|
|
14
|
+
self.assertEqual(hash(var_1), hash(var_3))
|
|
15
|
+
self.assertNotEqual(hash(var_1), hash(var_2))
|
|
16
|
+
self.assertNotEqual(hash(var_2), hash(var_3))
|
|
17
|
+
|
|
18
|
+
def test_scope_without_parent(self):
|
|
19
|
+
scope = Scope()
|
|
20
|
+
self.assertIs(scope, scope.exit())
|
|
21
|
+
|
|
22
|
+
def test_scope_with_parent(self):
|
|
23
|
+
parent_scope = Scope()
|
|
24
|
+
child_scope = parent_scope.enter()
|
|
25
|
+
self.assertIs(parent_scope, child_scope.exit())
|
|
26
|
+
|
|
27
|
+
def test_scope_contains(self):
|
|
28
|
+
scope = Scope()
|
|
29
|
+
scope.variables["x"] = Var("x", 10, int)
|
|
30
|
+
self.assertIn("x", scope)
|
|
31
|
+
self.assertNotIn("y", scope)
|
|
32
|
+
|
|
33
|
+
def test_scope_all_vars(self):
|
|
34
|
+
parent_scope = Scope()
|
|
35
|
+
parent_scope.variables["x"] = Var("x", 10, int)
|
|
36
|
+
child_scope = parent_scope.enter()
|
|
37
|
+
child_scope.variables["y"] = Var("y", 20, int)
|
|
38
|
+
|
|
39
|
+
all_vars = child_scope.get_all_vars_dict()
|
|
40
|
+
self.assertIn("x", all_vars)
|
|
41
|
+
self.assertIn("y", all_vars)
|
|
42
|
+
self.assertEqual(all_vars["x"].value, 10)
|
|
43
|
+
self.assertEqual(all_vars["y"].value, 20)
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
from typing import List
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class Var(object):
|
|
5
|
-
def __init__(self, var, value, type_):
|
|
6
|
-
self.var = var
|
|
7
|
-
self.value = value
|
|
8
|
-
self.type_ = type_
|
|
9
|
-
|
|
10
|
-
def __hash__(self):
|
|
11
|
-
return hash(self.var)
|
|
12
|
-
|
|
13
|
-
def __eq__(self, other):
|
|
14
|
-
return isinstance(other, Var) and self.var == other.var
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class Scope(object):
|
|
18
|
-
def __init__(self, parent=None, variables: dict = None):
|
|
19
|
-
self.parent = parent
|
|
20
|
-
self.variables = dict() if variables is None else variables.copy()
|
|
21
|
-
|
|
22
|
-
def enter(self):
|
|
23
|
-
return Scope(parent=self, variables=self.variables)
|
|
24
|
-
|
|
25
|
-
def exit(self):
|
|
26
|
-
if self.parent is not None:
|
|
27
|
-
return self.parent
|
|
28
|
-
else:
|
|
29
|
-
return self
|
|
30
|
-
|
|
31
|
-
def value(self, var: str) -> Var:
|
|
32
|
-
if var in self.variables:
|
|
33
|
-
return self.variables[var].value
|
|
34
|
-
|
|
35
|
-
def add(self, var, value, type_):
|
|
36
|
-
self.variables[var] = Var(var, value, type_)
|
|
37
|
-
|
|
38
|
-
def get_all_vars(self) -> List[Var]:
|
|
39
|
-
return list(self.variables.values())
|
sflkit-0.5.3/tests/test_scope.py
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
|
|
3
|
-
from sflkit.model.scope import Var, Scope
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class TestScope(unittest.TestCase):
|
|
7
|
-
def test_var_eq(self):
|
|
8
|
-
var_1 = Var("x", 2, int)
|
|
9
|
-
var_2 = Var("y", 2, int)
|
|
10
|
-
var_3 = Var("x", "", str)
|
|
11
|
-
self.assertEqual(var_1, var_3)
|
|
12
|
-
self.assertNotEqual(var_1, var_2)
|
|
13
|
-
self.assertNotEqual(var_2, var_3)
|
|
14
|
-
self.assertEqual(hash(var_1), hash(var_3))
|
|
15
|
-
self.assertNotEqual(hash(var_1), hash(var_2))
|
|
16
|
-
self.assertNotEqual(hash(var_2), hash(var_3))
|
|
17
|
-
|
|
18
|
-
def test_scope_without_parent(self):
|
|
19
|
-
scope = Scope()
|
|
20
|
-
self.assertIs(scope, scope.exit())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|