-
Notifications
You must be signed in to change notification settings - Fork 0
/
situation.py
147 lines (114 loc) · 5.39 KB
/
situation.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
import abc
import numpy as np
import pandas as pd
import const
class AbstractSituation(abc.ABC):
@abc.abstractmethod
def precondition(self, df: pd.DataFrame) -> pd.DataFrame:
pass
@abc.abstractmethod
def condition(self, df: pd.DataFrame) -> pd.DataFrame:
"""
Takes as input an already filtered pd.DataFrame.
:param df:
:return:
"""
pass
def __str__(self):
return self.__class__.__name__
def __eq__(self, other):
return str(self) == str(other)
class S0(AbstractSituation):
def precondition(self, df: pd.DataFrame) -> pd.DataFrame:
return df[
# behavior not involved (from env or from code)
(df[const.COLUMN_NAME_CHANGE_TYPE] != const.CHANGE_CAUSE_ENV) &
(df[const.COLUMN_NAME_CHANGE_TYPE] != const.CHANGE_CAUSE_CODE_ENV) &
# vulnerability not involved
(df[const.COLUMN_NAME_CHANGE_TYPE] != const.CHANGE_CAUSE_VULN)
]
def condition(self, df: pd.DataFrame) -> pd.DataFrame:
return df[
# no code changes
(df[const.COLUMN_NAME_CHANGE_TYPE] != const.CHANGE_CAUSE_CODE) |
# minor code changes with no impact on critical or novel components
((df[const.COLUMN_NAME_CODE_EXTENT] == const.CODE_EXTENT_MINOR) &
(df[const.COLUMN_NAME_CRITICAL] == const.CRITICAL_FALSE) &
(df[const.COLUMN_NAME_NOVELTY] == const.NOVELTY_FALSE))]
class S1(AbstractSituation):
def precondition(self, df: pd.DataFrame) -> pd.DataFrame:
return df[
# no vulnerabilities
(df[const.COLUMN_NAME_CHANGE_TYPE] != const.CHANGE_CAUSE_VULN) &
# no critical or novel componentes
(df[const.COLUMN_NAME_CRITICAL] ==
const.CRITICAL_FALSE) & (df[const.COLUMN_NAME_NOVELTY] == const.NOVELTY_FALSE)]
def condition(self, df: pd.DataFrame) -> pd.DataFrame:
return df[
# behavioral change from the environment
(df[const.COLUMN_NAME_CHANGE_TYPE] == const.CHANGE_CAUSE_ENV) |
# behavioral change caused by minor code changes
(
(df[const.COLUMN_NAME_CHANGE_TYPE] == const.CHANGE_CAUSE_CODE_ENV) &
(df[const.COLUMN_NAME_CODE_EXTENT] == const.CODE_EXTENT_MINOR)
) |
# major code change with no impact on the behavior
(
(df[const.COLUMN_NAME_CHANGE_TYPE] == const.CHANGE_CAUSE_CODE) &
(df[const.COLUMN_NAME_CODE_EXTENT] == const.CODE_EXTENT_MAJOR)
)
]
class S2(AbstractSituation):
def precondition(self, df: pd.DataFrame) -> pd.DataFrame:
return df
def condition(self, df: pd.DataFrame) -> pd.DataFrame:
return df[
# vulnerability is discovered
(df[const.COLUMN_NAME_CHANGE_TYPE] == const.CHANGE_CAUSE_VULN) |
# behavioral change caused by major code changes
(
(df[const.COLUMN_NAME_CHANGE_TYPE] == const.CHANGE_CAUSE_CODE_ENV) &
(df[const.COLUMN_NAME_CODE_EXTENT] == const.CODE_EXTENT_MAJOR)
)
]
class S3(AbstractSituation):
def precondition(self, df: pd.DataFrame) -> pd.DataFrame:
return df[
# no vulnerabilities
(df[const.COLUMN_NAME_CHANGE_TYPE] != const.CHANGE_CAUSE_VULN)
]
def condition(self, df: pd.DataFrame) -> pd.DataFrame:
# the condition here could be simplified, but it's not a problem
# (e.g., th first condition can be removed by setting >= 0 in the second.
return df[
# behavioral change with impact on critical component
((df[const.COLUMN_NAME_CHANGE_TYPE] == const.CHANGE_CAUSE_ENV) &
(df[const.COLUMN_NAME_CRITICAL] == const.CRITICAL_TRUE)) |
# code change with impact on critical component
((df[const.COLUMN_NAME_CHANGE_TYPE] == const.CHANGE_CAUSE_CODE) &
(df[const.COLUMN_NAME_CRITICAL] == const.CRITICAL_TRUE)) |
# code change with impact on novel component
((df[const.COLUMN_NAME_CHANGE_TYPE] == const.CHANGE_CAUSE_CODE) &
(df[const.COLUMN_NAME_NOVELTY] == const.NOVELTY_TRUE)) |
# code change with impact on behavior and on critical component
((df[const.COLUMN_NAME_CHANGE_TYPE] == const.CHANGE_CAUSE_CODE_ENV) &
(df[const.COLUMN_NAME_CRITICAL] == const.CRITICAL_TRUE))
]
def applies(df: pd.DataFrame) -> pd.DataFrame:
# the indices where to apply the situation understanding.
# Initially equal to all the indices in df.
filtered_indices = df.index
# accumulated_removed_indices = df.index
indices_removed_previously = np.array([])
# add the column containing the situation.
out = df.copy()
out[const.COLUMN_NAME_SITUATION] = 'S4'
for situation in [S0(), S1(), S2(), S3()]:
pre_df = situation.precondition(df.iloc[filtered_indices])
cond_df = situation.condition(pre_df)
out.loc[cond_df.index, 'S'] = str(situation)
indices_removed_previously = np.union1d(indices_removed_previously, cond_df.index)
# at the next round, we operate on a dataset
# containing all the initial points except those matched at this round (and at the previous).
filtered_indices = np.setdiff1d(df.index, indices_removed_previously)
return out