flamapy 2.0.0.dev4__tar.gz → 2.1.0.dev0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flamapy
3
- Version: 2.0.0.dev4
3
+ Version: 2.1.0.dev0
4
4
  Summary: Flamapy feature model is a distribution of the flama framework containing all plugins required to analyze feature models. It also offers a richier API and a complete command line interface and documentation.
5
5
  Home-page: https://github.com/flamapy/flamapy-feature-model
6
6
  Author: Flamapy
@@ -9,19 +9,21 @@ from typing import List, Tuple, Optional
9
9
  from types import FunctionType
10
10
 
11
11
  from flamapy.interfaces.python.flamapy_feature_model import FLAMAFeatureModel
12
+
12
13
  # List to store registered commands and their arguments
13
14
  MANUAL_COMMANDS = []
14
15
 
15
16
 
16
17
  def command(name, description, *args): # type: ignore
17
-
18
18
  def decorator(func): # type: ignore
19
19
  MANUAL_COMMANDS.append((name, description, func, args))
20
20
 
21
21
  @wraps(func)
22
22
  def wrapper(*func_args, **func_kwargs): # type: ignore
23
23
  return func(*func_args, **func_kwargs)
24
+
24
25
  return wrapper
26
+
25
27
  return decorator
26
28
 
27
29
 
@@ -38,17 +40,20 @@ def extract_commands(cls: type) -> List[Tuple[str, str, FunctionType, List[inspe
38
40
  return commands
39
41
 
40
42
 
41
- @command('generate_plugin', """This command generates a new plugin to implement your
43
+ @command(
44
+ "generate_plugin",
45
+ """This command generates a new plugin to implement your
42
46
  cusom operations. To execute it you should set yourself in the path of the
43
- flamapy src directory""",
44
- ('name', str, 'The pluggins name'),
45
- ('extension', str, 'The extansion to be registered with the flamapy ecosystem'),
46
- ('path', str, 'The path to generate it'))
47
+ flamapy src directory""",
48
+ ("name", str, "The pluggins name"),
49
+ ("extension", str, "The extansion to be registered with the flamapy ecosystem"),
50
+ ("path", str, "The path to generate it"),
51
+ )
47
52
  def generate_plugin(args): # type: ignore
48
53
  name = args.name
49
54
  ext = args.extension
50
55
  dst = args.path
51
- src = 'skel_metamodel/'
56
+ src = "skel_metamodel/"
52
57
 
53
58
  # Check DST exist
54
59
  if not os.path.isdir(dst):
@@ -70,42 +75,48 @@ def generate_plugin(args): # type: ignore
70
75
 
71
76
  copy_files = copytree(src, dst, dirs_exist_ok=True)
72
77
 
73
- for copy_file in Path(copy_files).glob('**/*'):
78
+ for copy_file in Path(copy_files).glob("**/*"):
74
79
  if copy_file.is_dir():
75
80
  continue
76
81
  with open(copy_file, "r", encoding="utf-8") as file:
77
82
  lines = file.readlines()
78
83
  with open(copy_file, "w", encoding="utf-8") as filewrite:
79
84
  for line in lines:
80
- out_line = line.replace('__NAME__', name.capitalize()).replace('__EXT__', ext)
85
+ out_line = line.replace("__NAME__", name.capitalize()).replace("__EXT__", ext)
81
86
  filewrite.write(out_line)
82
87
 
83
- os.rename(os.path.join(dst, 'flamapy/metamodels/__NAME__'),
84
- os.path.join(dst, f'flamapy/metamodels/{name}'))
88
+ os.rename(
89
+ os.path.join(dst, "flamapy/metamodels/__NAME__"),
90
+ os.path.join(dst, f"flamapy/metamodels/{name}"),
91
+ )
85
92
  print("Plugin generated!")
86
93
 
87
94
 
88
95
  def setup_dynamic_commands(subparsers, dynamic_commands): # type: ignore
89
96
  for name, docstring, method, parameters in dynamic_commands:
90
97
  subparser = subparsers.add_parser(name, help=docstring)
91
- subparser.add_argument('model_path', type=str, help='Path to the feature model file')
92
- if 'configuration_path' in [param.name for param in parameters]:
93
- subparser.add_argument('--configuration_path',
94
- type=str,
95
- help='Path to the configuration file',
96
- required=False)
98
+ subparser.add_argument("model_path", type=str, help="Path to the feature model file")
99
+ if "configuration_path" in [param.name for param in parameters]:
100
+ subparser.add_argument(
101
+ "--configuration_path",
102
+ type=str,
103
+ help="Path to the configuration file",
104
+ required=False,
105
+ )
97
106
  for param in parameters:
98
107
  arg_name = param.name
99
- if arg_name not in ['model_path']: # Avoid duplicates
108
+ if arg_name not in ["model_path"]: # Avoid duplicates
100
109
  if param.default == param.empty: # Positional argument
101
- subparser.add_argument(arg_name,
102
- type=param.annotation,
103
- help=param.annotation.__name__)
110
+ subparser.add_argument(
111
+ arg_name, type=param.annotation, help=param.annotation.__name__
112
+ )
104
113
  else: # Optional argument
105
- subparser.add_argument(f'--{arg_name}',
106
- type=param.annotation,
107
- default=param.default,
108
- help=f'Optional {param.annotation.__name__}')
114
+ subparser.add_argument(
115
+ f"--{arg_name}",
116
+ type=param.annotation,
117
+ default=param.default,
118
+ help=f"Optional {param.annotation.__name__}",
119
+ )
109
120
  subparser.set_defaults(func=method, method_name=name, parameters=parameters)
110
121
 
111
122
 
@@ -120,7 +131,7 @@ def setup_manual_commands(subparsers, manual_commands): # type: ignore
120
131
 
121
132
  def execute_command(args: argparse.Namespace) -> None:
122
133
  try:
123
- if hasattr(args, 'method_name'):
134
+ if hasattr(args, "method_name"):
124
135
  cls_instance = FLAMAFeatureModel(args.model_path)
125
136
  method_parameters = [param.name for param in args.parameters]
126
137
  command_args = {k: v for k, v in vars(args).items() if k in method_parameters}
@@ -130,7 +141,7 @@ def execute_command(args: argparse.Namespace) -> None:
130
141
  print(result)
131
142
  else:
132
143
  func = args.func
133
- command_args = {k: v for k, v in vars(args).items() if k != 'func'}
144
+ command_args = {k: v for k, v in vars(args).items() if k != "func"}
134
145
  result = func(args)
135
146
  if result is not None:
136
147
  print(result)
@@ -147,8 +158,8 @@ def execute_command(args: argparse.Namespace) -> None:
147
158
 
148
159
 
149
160
  def flamapy_cli() -> None:
150
- parser = argparse.ArgumentParser(description='FLAMA Feature Model CLI')
151
- subparsers = parser.add_subparsers(dest='command')
161
+ parser = argparse.ArgumentParser(description="FLAMA Feature Model CLI")
162
+ subparsers = parser.add_subparsers(dest="command")
152
163
 
153
164
  dynamic_commands = extract_commands(FLAMAFeatureModel)
154
165
  setup_dynamic_commands(subparsers, dynamic_commands)
@@ -165,4 +176,4 @@ def flamapy_cli() -> None:
165
176
  print("Framework developers operations:")
166
177
  for name, description, _, _ in MANUAL_COMMANDS:
167
178
  print(f" {name}: {description}")
168
- print("Execute flamapy --help for more information")
179
+ print("Execute flamapy --help for more information")
@@ -0,0 +1,3 @@
1
+ from .flamapy_feature_model import FLAMAFeatureModel
2
+
3
+ __all__ = ["FLAMAFeatureModel"]
@@ -5,11 +5,10 @@ from flamapy.core.exceptions import FlamaException
5
5
  from flamapy.metamodels.configuration_metamodel.models import Configuration
6
6
 
7
7
 
8
- class FLAMAFeatureModel:
9
-
8
+ class FLAMAFeatureModel:
10
9
  def __init__(self, model_path: str):
11
10
  """
12
- This is the path in the filesystem where the model is located.
11
+ This is the path in the filesystem where the model is located.
13
12
  Any model in UVL, FaMaXML or FeatureIDE format are accepted
14
13
  """
15
14
  self.model_path = model_path
@@ -28,7 +27,7 @@ class FLAMAFeatureModel:
28
27
  self.bdd_model = None
29
28
 
30
29
  def _read(self, model_path: str) -> FeatureModel:
31
- return self.discover_metamodel.use_transformation_t2m(model_path, 'fm')
30
+ return self.discover_metamodel.use_transformation_t2m(model_path, "fm")
32
31
 
33
32
  def _transform_to_sat(self) -> None:
34
33
  if self.sat_model is None:
@@ -39,17 +38,18 @@ class FLAMAFeatureModel:
39
38
  self.bdd_model = self.discover_metamodel.use_transformation_m2m(self.fm_model, "bdd")
40
39
 
41
40
  def atomic_sets(self) -> Union[None, List[List[Any]]]:
42
- """
41
+ """
43
42
  This operation is used to find the atomic sets in a model:
44
- It returns the atomic sets if they are found in the model.
45
- If the model does not follow the UVL specification, an
43
+ It returns the atomic sets if they are found in the model.
44
+ If the model does not follow the UVL specification, an
46
45
  exception is raised and the operation returns False.
47
46
  """
48
47
 
49
48
  # Try to use the Find operation, which returns the atomic sets if they are found
50
49
  try:
51
- atomic_sets = self.discover_metamodel.use_operation(self.fm_model,
52
- 'FMAtomicSets').get_result()
50
+ atomic_sets = self.discover_metamodel.use_operation(
51
+ self.fm_model, "FMAtomicSets"
52
+ ).get_result()
53
53
  result = []
54
54
  for atomic_set in atomic_sets:
55
55
  partial_set = []
@@ -62,66 +62,69 @@ class FLAMAFeatureModel:
62
62
  return None
63
63
 
64
64
  def average_branching_factor(self) -> Union[None, float]:
65
- """
66
- This refers to the average number of child features that a parent feature has in a
67
- feature model. It's calculated by dividing the total number of child features by the
68
- total number of parent features. A high average branching factor indicates a complex
69
- feature model with many options, while a low average branching factor indicates a
65
+ """
66
+ This refers to the average number of child features that a parent feature has in a
67
+ feature model. It's calculated by dividing the total number of child features by the
68
+ total number of parent features. A high average branching factor indicates a complex
69
+ feature model with many options, while a low average branching factor indicates a
70
70
  simpler model.
71
71
  """
72
72
 
73
73
  # Try to use the Find operation, which returns the atomic sets if they are found
74
74
  try:
75
- result = self.discover_metamodel.use_operation(self.fm_model,
76
- 'FMAverageBranchingFactor').get_result()
75
+ result = self.discover_metamodel.use_operation(
76
+ self.fm_model, "FMAverageBranchingFactor"
77
+ ).get_result()
77
78
  return result
78
79
  except FlamaException as exception:
79
80
  print(f"Error: {exception}")
80
81
  return None
81
82
 
82
83
  def count_leafs(self) -> Union[None, int]:
83
- """
84
- This operation counts the number of leaf features in a feature model. Leaf features
85
- are those that do not have any child features. They represent the most specific
84
+ """
85
+ This operation counts the number of leaf features in a feature model. Leaf features
86
+ are those that do not have any child features. They represent the most specific
86
87
  options in a product line.
87
88
  """
88
89
 
89
90
  # Try to use the Find operation, which returns the atomic sets if they are found
90
91
  try:
91
- result = self.discover_metamodel.use_operation(self.fm_model,
92
- 'FMCountLeafs').get_result()
92
+ result = self.discover_metamodel.use_operation(
93
+ self.fm_model, "FMCountLeafs"
94
+ ).get_result()
93
95
  return result
94
96
  except FlamaException as exception:
95
97
  print(f"Error: {exception}")
96
98
  return None
97
99
 
98
100
  def estimated_number_of_configurations(self) -> Union[None, int]:
99
- """
100
- This is an estimate of the total number of different products that can be produced
101
- from a feature model. It's calculated by considering all possible combinations of
102
- features. This can be a simple multiplication if all features are independent, but
103
- in most cases, constraints and dependencies between features need to be taken
104
- into account.
101
+ """
102
+ This is an estimate of the total number of different products that can be produced
103
+ from a feature model. It's calculated by considering all possible combinations of
104
+ features. This can be a simple multiplication if all features are independent, but
105
+ in most cases, constraints and dependencies between features need to be taken
106
+ into account.
105
107
  """
106
108
 
107
109
  # Try to use the Find operation, which returns the atomic sets if they are found
108
110
  try:
109
111
  result = self.discover_metamodel.use_operation(
110
- self.fm_model, 'FMEstimatedConfigurationsNumber').get_result()
112
+ self.fm_model, "FMEstimatedConfigurationsNumber"
113
+ ).get_result()
111
114
  return result
112
115
  except FlamaException as exception:
113
116
  print(f"Error: {exception}")
114
117
  return None
115
118
 
116
119
  def feature_ancestors(self, feature_name: str) -> Union[None, List[str]]:
117
- '''
118
- These are the features that are directly or indirectly the parent of a given feature in
119
- a feature model. Ancestors of a feature are found by traversing up the feature hierarchy.
120
+ """
121
+ These are the features that are directly or indirectly the parent of a given feature in
122
+ a feature model. Ancestors of a feature are found by traversing up the feature hierarchy.
120
123
  This information can be useful to understand the context and dependencies of a feature.
121
- '''
124
+ """
122
125
  # Try to use the Find operation, which returns the atomic sets if they are found
123
126
  try:
124
- operation = self.discover_metamodel.get_operation(self.fm_model, 'FMFeatureAncestors')
127
+ operation = self.discover_metamodel.get_operation(self.fm_model, "FMFeatureAncestors")
125
128
  operation.set_feature(self.fm_model.get_feature_by_name(feature_name))
126
129
  operation.execute(self.fm_model)
127
130
  flama_result = operation.get_result()
@@ -134,22 +137,23 @@ class FLAMAFeatureModel:
134
137
  return None
135
138
 
136
139
  def leaf_features(self) -> Union[None, List[str]]:
137
- """
140
+ """
138
141
  This operation is used to find leaf features in a model:
139
- It returns the leaf features if they are found in the model.
140
- If the model does not follow the UVL specification, an
142
+ It returns the leaf features if they are found in the model.
143
+ If the model does not follow the UVL specification, an
141
144
  exception is raised and the operation returns False.
142
145
 
143
- Traditionally you would use the flama tool by
146
+ Traditionally you would use the flama tool by
144
147
  features = discover_metamodel.use_operation_from_file('OperationString', model)
145
- however, in this tool we know that this operation is from the fm metamodel,
148
+ however, in this tool we know that this operation is from the fm metamodel,
146
149
  so we avoid to execute the transformation if possible
147
150
  """
148
151
 
149
152
  # Try to use the operation, which returns the leaf features if they are found
150
153
  try:
151
- features = self.discover_metamodel.use_operation(self.fm_model,
152
- 'FMLeafFeatures').get_result()
154
+ features = self.discover_metamodel.use_operation(
155
+ self.fm_model, "FMLeafFeatures"
156
+ ).get_result()
153
157
  leaf_features = []
154
158
  for feature in features:
155
159
  leaf_features.append(feature.name)
@@ -159,34 +163,36 @@ class FLAMAFeatureModel:
159
163
  return None
160
164
 
161
165
  def max_depth(self) -> Union[None, int]:
162
- """
166
+ """
163
167
  This operation is used to find the max depth of the tree in a model:
164
- It returns the max depth of the tree.
165
- If the model does not follow the UVL specification, an
168
+ It returns the max depth of the tree.
169
+ If the model does not follow the UVL specification, an
166
170
  exception is raised and the operation returns False.
167
171
  """
168
172
 
169
173
  # Try to use the Find operation, which returns the max depth of the tree
170
174
  try:
171
- return self.discover_metamodel.use_operation(self.fm_model,
172
- 'FMMaxDepthTree').get_result()
175
+ return self.discover_metamodel.use_operation(
176
+ self.fm_model, "FMMaxDepthTree"
177
+ ).get_result()
173
178
  except FlamaException as exception:
174
179
  print(f"Error: {exception}")
175
180
  return None
176
181
 
177
- #The methods above rely on sat to be executed.
182
+ # The methods above rely on sat to be executed.
178
183
  def core_features(self) -> Union[None, List[str]]:
179
184
  """
180
- These are the features that are present in all products of a product line.
181
- In a feature model, they are the features that are mandatory and not optional.
182
- Core features define the commonality among all products in a product line.
185
+ These are the features that are present in all products of a product line.
186
+ In a feature model, they are the features that are mandatory and not optional.
187
+ Core features define the commonality among all products in a product line.
183
188
  This call requires sat to be called, however, there is an implementation within
184
- flamapy that does not requires sat. please use the framework in case of needing it.
189
+ flamapy that does not requires sat. please use the framework in case of needing it.
185
190
  """
186
191
  try:
187
192
  self._transform_to_sat()
188
- features = self.discover_metamodel.use_operation(self.sat_model,
189
- 'PySATCoreFeatures').get_result()
193
+ features = self.discover_metamodel.use_operation(
194
+ self.sat_model, "PySATCoreFeatures"
195
+ ).get_result()
190
196
  return features
191
197
  except FlamaException as exception:
192
198
  print(f"Error: {exception}")
@@ -194,14 +200,15 @@ class FLAMAFeatureModel:
194
200
 
195
201
  def dead_features(self) -> Union[None, List[str]]:
196
202
  """
197
- These are features that, due to the constraints and dependencies in the
198
- feature model, cannot be included in any valid product. Dead features are usually
203
+ These are features that, due to the constraints and dependencies in the
204
+ feature model, cannot be included in any valid product. Dead features are usually
199
205
  a sign of an error in the feature model.
200
206
  """
201
207
  try:
202
208
  self._transform_to_sat()
203
- features = self.discover_metamodel.use_operation(self.sat_model,
204
- 'PySATDeadFeatures').get_result()
209
+ features = self.discover_metamodel.use_operation(
210
+ self.sat_model, "PySATDeadFeatures"
211
+ ).get_result()
205
212
  return features
206
213
  except FlamaException as exception:
207
214
  print(f"Error: {exception}")
@@ -209,14 +216,15 @@ class FLAMAFeatureModel:
209
216
 
210
217
  def false_optional_features(self) -> Union[None, List[str]]:
211
218
  """
212
- These are features that appear to be optional in the feature model, but due to the
213
- constraints and dependencies, must be included in every valid product. Like dead features,
219
+ These are features that appear to be optional in the feature model, but due to the
220
+ constraints and dependencies, must be included in every valid product. Like dead features,
214
221
  false optional features are usually a sign of an error in the feature model.
215
222
  """
216
223
  try:
217
224
  self._transform_to_sat()
218
- operation = self.discover_metamodel.get_operation(self.sat_model,
219
- 'PySATFalseOptionalFeatures')
225
+ operation = self.discover_metamodel.get_operation(
226
+ self.sat_model, "PySATFalseOptionalFeatures"
227
+ )
220
228
  operation.feature_model = self.fm_model
221
229
  operation.execute(self.sat_model)
222
230
  features = operation.get_result()
@@ -227,15 +235,16 @@ class FLAMAFeatureModel:
227
235
 
228
236
  def filter(self, configuration_path: str) -> Union[None, List[Configuration]]:
229
237
  """
230
- This operation selects a subset of the products of a product line based on certain
231
- criteria. For example, you might filter the products to only include those that
238
+ This operation selects a subset of the products of a product line based on certain
239
+ criteria. For example, you might filter the products to only include those that
232
240
  contain a certain feature.
233
241
  """
234
242
  try:
235
243
  self._transform_to_sat()
236
- configuration = self.discover_metamodel.use_transformation_t2m(configuration_path,
237
- 'configuration')
238
- operation = self.discover_metamodel.get_operation(self.sat_model, 'PySATFilter')
244
+ configuration = self.discover_metamodel.use_transformation_t2m(
245
+ configuration_path, "configuration"
246
+ )
247
+ operation = self.discover_metamodel.get_operation(self.sat_model, "PySATFilter")
239
248
  operation.set_configuration(configuration)
240
249
  operation.execute(self.sat_model)
241
250
  result = operation.get_result()
@@ -246,9 +255,9 @@ class FLAMAFeatureModel:
246
255
 
247
256
  def configurations_number(self, with_sat: bool = False) -> Union[None, int]:
248
257
  """
249
- This is the total number of different full configurations that can be
250
- produced from a feature model. It's calculated by considering all possible
251
- combinations of features, taking into account the constraints and
258
+ This is the total number of different full configurations that can be
259
+ produced from a feature model. It's calculated by considering all possible
260
+ combinations of features, taking into account the constraints and
252
261
  dependencies between features.
253
262
  """
254
263
  try:
@@ -256,12 +265,12 @@ class FLAMAFeatureModel:
256
265
  if with_sat:
257
266
  self._transform_to_sat()
258
267
  nop = self.discover_metamodel.use_operation(
259
- self.sat_model, 'PySATConfigurationsNumber'
268
+ self.sat_model, "PySATConfigurationsNumber"
260
269
  ).get_result()
261
270
  else:
262
271
  self._transform_to_bdd()
263
272
  nop = self.discover_metamodel.use_operation(
264
- self.bdd_model, 'BDDConfigurationsNumber'
273
+ self.bdd_model, "BDDConfigurationsNumber"
265
274
  ).get_result()
266
275
  return nop
267
276
  except FlamaException as exception:
@@ -270,22 +279,22 @@ class FLAMAFeatureModel:
270
279
 
271
280
  def configurations(self, with_sat: bool = False) -> Union[None, List[Configuration]]:
272
281
  """
273
- These are the individual outcomes that can be produced from a feature model. Each product
274
- is a combination of features that satisfies all the constraints and dependencies in the
282
+ These are the individual outcomes that can be produced from a feature model. Each product
283
+ is a combination of features that satisfies all the constraints and dependencies in the
275
284
  feature model.
276
285
  """
277
286
  try:
278
287
  products = []
279
288
  if with_sat:
280
289
  self._transform_to_sat()
281
- products = self.discover_metamodel.use_operation(self.sat_model,
282
- 'PySATConfigurations'
283
- ).get_result()
290
+ products = self.discover_metamodel.use_operation(
291
+ self.sat_model, "PySATConfigurations"
292
+ ).get_result()
284
293
  else:
285
294
  self._transform_to_bdd()
286
- products = self.discover_metamodel.use_operation(self.bdd_model,
287
- 'BDDConfigurations'
288
- ).get_result()
295
+ products = self.discover_metamodel.use_operation(
296
+ self.bdd_model, "BDDConfigurations"
297
+ ).get_result()
289
298
  return products
290
299
  except FlamaException as exception:
291
300
  print(f"Error: {exception}")
@@ -293,16 +302,17 @@ class FLAMAFeatureModel:
293
302
 
294
303
  def commonality(self, configuration_path: str) -> Union[None, float]:
295
304
  """
296
- This is a measure of how often a feature appears in the products of a
297
- product line. It's usually expressed as a percentage. A feature with
305
+ This is a measure of how often a feature appears in the products of a
306
+ product line. It's usually expressed as a percentage. A feature with
298
307
  100 per cent commonality is a core feature, as it appears in all products.
299
308
  """
300
309
  try:
301
310
  self._transform_to_sat()
302
- configuration = self.discover_metamodel.use_transformation_t2m(configuration_path,
303
- 'configuration')
311
+ configuration = self.discover_metamodel.use_transformation_t2m(
312
+ configuration_path, "configuration"
313
+ )
304
314
 
305
- operation = self.discover_metamodel.get_operation(self.sat_model, 'PySATCommonality')
315
+ operation = self.discover_metamodel.get_operation(self.sat_model, "PySATCommonality")
306
316
  operation.set_configuration(configuration)
307
317
  operation.execute(self.sat_model)
308
318
  return operation.get_result()
@@ -310,25 +320,28 @@ class FLAMAFeatureModel:
310
320
  print(f"Error: {exception}")
311
321
  return None
312
322
 
313
- def satisfiable_configuration(self,
314
- configuration_path: str,
315
- full_configuration: bool = False) -> Union[None, bool]:
323
+ def satisfiable_configuration(
324
+ self, configuration_path: str, full_configuration: bool = False
325
+ ) -> Union[None, bool]:
316
326
  """
317
- This is a product that is produced from a valid configuration of features. A valid
327
+ This is a product that is produced from a valid configuration of features. A valid
318
328
  product satisfies all the constraints and dependencies in the feature model.
319
329
  """
320
330
  try:
321
331
  self._transform_to_sat()
322
- configuration = self.discover_metamodel.use_transformation_t2m(configuration_path,
323
- 'configuration')
324
- operation = self.discover_metamodel.get_operation(self.sat_model,
325
- 'PySATSatisfiableConfiguration')
332
+ configuration = self.discover_metamodel.use_transformation_t2m(
333
+ configuration_path, "configuration"
334
+ )
335
+ operation = self.discover_metamodel.get_operation(
336
+ self.sat_model, "PySATSatisfiableConfiguration"
337
+ )
326
338
 
327
339
  if full_configuration:
328
- operation.set_configuration(configuration, is_full=True)
340
+ configuration.is_full = True
329
341
  else:
330
- operation.set_configuration(configuration, is_full=False)
342
+ configuration.is_full = False
331
343
 
344
+ operation.set_configuration(configuration)
332
345
  operation.execute(self.sat_model)
333
346
  result = operation.get_result()
334
347
  return result
@@ -338,15 +351,16 @@ class FLAMAFeatureModel:
338
351
 
339
352
  def satisfiable(self) -> Union[None, bool]:
340
353
  """
341
- In the context of feature models, this usually refers to whether the feature model itself
342
- satisfies all the constraints and dependencies. A a valid feature model is one that
354
+ In the context of feature models, this usually refers to whether the feature model itself
355
+ satisfies all the constraints and dependencies. A a valid feature model is one that
343
356
  does encodes at least a single valid product.
344
357
  """
345
358
  try:
346
359
  self._transform_to_sat()
347
- result = self.discover_metamodel.use_operation(self.sat_model,
348
- 'PySATSatisfiable').get_result()
360
+ result = self.discover_metamodel.use_operation(
361
+ self.sat_model, "PySATSatisfiable"
362
+ ).get_result()
349
363
  return result
350
364
  except FlamaException as exception:
351
365
  print(f"Error: {exception}")
352
- return None
366
+ return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flamapy
3
- Version: 2.0.0.dev4
3
+ Version: 2.1.0.dev0
4
4
  Summary: Flamapy feature model is a distribution of the flama framework containing all plugins required to analyze feature models. It also offers a richier API and a complete command line interface and documentation.
5
5
  Home-page: https://github.com/flamapy/flamapy-feature-model
6
6
  Author: Flamapy
@@ -1,4 +1,5 @@
1
1
  README.md
2
+ pyproject.toml
2
3
  setup.py
3
4
  flamapy.egg-info/PKG-INFO
4
5
  flamapy.egg-info/SOURCES.txt
@@ -0,0 +1,12 @@
1
+ wheel
2
+ flamapy-fw~=2.1.0.dev0
3
+ flamapy-fm~=2.1.0.dev0
4
+ flamapy-sat~=2.1.0.dev0
5
+ flamapy-bdd~=2.1.0.dev0
6
+
7
+ [dev]
8
+ pytest
9
+ pytest-mock
10
+ prospector
11
+ mypy
12
+ coverage
@@ -0,0 +1,55 @@
1
+ [tool.ruff]
2
+ line-length = 100 # Matches max-line-length from pycodestyle
3
+ target-version = "py38" # Adjust if using another Python version
4
+
5
+ [tool.ruff.lint]
6
+ select = ["E", "W", "F", "C", "PL", "RUF"] # Includes pycodestyle, pylint, and McCabe complexity
7
+ ignore = [
8
+ "RUF012", # Equivalent to Pylint's super-init-not-called
9
+ "RUF002", # Weird symbols on docstring
10
+ "RUF001", # Weird symbols string
11
+ ]
12
+
13
+ [tool.ruff.lint.mccabe]
14
+ max-complexity = 10 # Equivalent to enabling mccabe in Prospector
15
+
16
+ [tool.ruff.lint.per-file-ignores]
17
+ "flamapy/metamodels/fm_metamodel/transformations/pysat_to_fm.py" = ["ALL"] # Ignore this file entirely
18
+ "tests/*" = ["ALL"] # Ignore all test files
19
+ "build/*" = ["ALL"]
20
+ "resources/*" = ["ALL"]
21
+ ".mypy_cache/*" = ["ALL"]
22
+ "venv/*" = ["ALL"]
23
+ ".venv/*" = ["ALL"]
24
+ "env/*" = ["ALL"]
25
+ "flamapy_fm.egg-info/*" = ["ALL"]
26
+ "__pycache__/*" = ["ALL"]
27
+ "skel_metamodel/*" = ["ALL"]
28
+ "flamapy/__init__.py" = ["ALL"]
29
+
30
+ [tool.ruff.lint.pycodestyle]
31
+ max-line-length = 100 # Matches your existing pycodestyle setting
32
+
33
+ # MYPY CONFIGURATION
34
+ [tool.mypy]
35
+ scripts_are_modules = true
36
+ show_traceback = true
37
+
38
+ # Strict checking
39
+ check_untyped_defs = true
40
+ disallow_untyped_defs = true
41
+ disallow_any_generics = true
42
+ warn_no_return = true
43
+ strict_optional = true
44
+ no_implicit_optional = true
45
+ warn_redundant_casts = true
46
+ warn_unused_ignores = true
47
+
48
+ # Show error codes for type: ignore comments
49
+ show_error_codes = true
50
+
51
+ # Suppress missing imports errors
52
+ ignore_missing_imports = true
53
+
54
+ # Warn about unreachable or redundant code
55
+ warn_unreachable = true
@@ -4,10 +4,12 @@ import setuptools
4
4
  with open("README.md", "r") as fh:
5
5
  long_description = fh.read()
6
6
 
7
+
7
8
  def read_requirements(file):
8
9
  with open(file, "r") as fh:
9
10
  return fh.read().splitlines()
10
11
 
12
+
11
13
  # Read requirements from the requirements.txt file
12
14
  requirements = read_requirements("requirements.txt")
13
15
 
@@ -16,27 +18,28 @@ dev_requirements = read_requirements("requirements-dev.txt")
16
18
 
17
19
  setuptools.setup(
18
20
  name="flamapy",
19
- version="2.0.0.dev4",
21
+ version="2.1.0.dev0",
20
22
  author="Flamapy",
21
23
  author_email="flamapy@us.es",
22
- description="Flamapy feature model is a distribution of the flama framework containing all plugins required to analyze feature models. It also offers a richier API and a complete command line interface and documentation.",
24
+ description="Flamapy feature model is a distribution of the " \
25
+ "flama framework containing all plugins required to analyze " \
26
+ "feature models. It also offers a richier API and a complete " \
27
+ "command line interface and documentation.",
23
28
  long_description=long_description,
24
29
  long_description_content_type="text/markdown",
25
30
  url="https://github.com/flamapy/flamapy-feature-model",
26
- packages=setuptools.find_namespace_packages(include=['flamapy.*']),
31
+ packages=setuptools.find_namespace_packages(include=["flamapy.*"]),
27
32
  classifiers=[
28
33
  "Programming Language :: Python :: 3",
29
34
  "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
30
35
  "Operating System :: OS Independent",
31
36
  ],
32
- python_requires='>=3.9',
37
+ python_requires=">=3.9",
33
38
  install_requires=requirements,
34
- extras_require={
35
- 'dev': dev_requirements
36
- },
39
+ extras_require={"dev": dev_requirements},
37
40
  entry_points={
38
- 'console_scripts': [
39
- 'flamapy = flamapy.commands:flamapy_cli',
41
+ "console_scripts": [
42
+ "flamapy = flamapy.commands:flamapy_cli",
40
43
  ],
41
44
  },
42
45
  )
@@ -1,5 +0,0 @@
1
- from .flamapy_feature_model import (
2
- FLAMAFeatureModel
3
- )
4
-
5
- __all__ = ['FLAMAFeatureModel']
@@ -1,12 +0,0 @@
1
- wheel
2
- flamapy-fw==2.0.0.dev7
3
- flamapy-fm==2.0.0.dev8
4
- flamapy-sat==2.0.0.dev8
5
- flamapy-bdd==2.0.0.dev10
6
-
7
- [dev]
8
- pytest
9
- pytest-mock
10
- prospector
11
- mypy
12
- coverage
File without changes
File without changes