flamapy 2.0.0.dev2__tar.gz → 2.0.0.dev3__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.
@@ -0,0 +1,100 @@
1
+ Metadata-Version: 2.1
2
+ Name: flamapy
3
+ Version: 2.0.0.dev3
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
+ Home-page: https://github.com/flamapy/flamapy-feature-model
6
+ Author: Flamapy
7
+ Author-email: flamapy@us.es
8
+ License: UNKNOWN
9
+ Platform: UNKNOWN
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+ Provides-Extra: dev
16
+
17
+ <div align="center">
18
+
19
+ <a href="">[![Pytest Testing Suite](https://github.com/flamapy/flamapy/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/flamapy/flamapy/actions/workflows/tests.yml)</a>
20
+ <a href="">[![Commits Syntax Checker](https://github.com/flamapy/flamapy/actions/workflows/commits.yml/badge.svg?branch=main)](https://github.com/flamapy/flamapy/actions/workflows/commits.yml)</a>
21
+ <a href="">![PyPI](https://img.shields.io/pypi/v/flamapy?label=pypi%20package)
22
+ <a href="">![PyPI - Downloads](https://img.shields.io/pypi/dm/flamapy)
23
+ </div>
24
+
25
+ #
26
+
27
+ <div id="top"></div>
28
+ <br />
29
+ <div align="center">
30
+
31
+ <h3 align="center">FLAMAPY</h3>
32
+
33
+ <p align="center">
34
+ A new and easy way to use FLAMA
35
+ <br />
36
+ <a href="https://github.com/flamapy/flamapy/issues">Report Bug</a>
37
+ ·
38
+ <a href="https://github.com/flamapy/flamapy/issues">Request Feature</a>
39
+ </p>
40
+ </div>
41
+ <!-- ABOUT THE PROJECT -->
42
+
43
+ # About The Project
44
+ FLAMAPY Feature model distribution provides an easier way of using FLAMAPY when analysing feature models. It packs the most used plugins for analyis of feature models adding a layer of convenience to use the framework or integrate it. If some other operations are required please see in the [documentation](flamapy.github.io/docs) if its supported in the ecosystem though the Python interface.
45
+
46
+ Feature Model Analysis has a crucial role in software product line engineering, enabling us to understand, design, and validate the complex relationships among features in a software product line. These feature models can often be complex and challenging to analyze due to their variability, making it difficult to identify conflicts, dead features, and potential optimizations. This is where this distribution comes in.
47
+
48
+ # Using the CMD
49
+ ```bash
50
+ flamapy --help #This will show the commands available
51
+ flamapy satisfiable <path to file> to check if a model is valid
52
+ ...
53
+ ```
54
+ # Using the Python interface
55
+ This is simple, Flama FM dist in hosted in pypi, therefore simply add the package flama-fm-dist to your requirements file and call the API as follows:
56
+
57
+ ```python
58
+ from flamapy.interfaces.python.flama_feature_model import FLAMAFeatureModel
59
+
60
+ fm = FLAMAFeatureModel("path/to/feature/model")
61
+ print(fm.valid())
62
+ ```
63
+ # Operations available:
64
+ Currently this distribution offers a subset of the operations available in the ecosystem, in the case of the feature mdoel distribution, we provide those operations that are well tested and used by the community. Nonetheless, If other more complex operations are required you can rely on the python interface of the framework to execute them all.
65
+
66
+ * atomic_sets: This operation is used to find the atomic sets in a model: It returns the atomic sets if they are found in the model. If the model does not follow the UVL specification, an exception is raised and the operation returns False.
67
+
68
+ * average_branching_factor:This refers to the average number of child features that a parent feature has in a feature model. It's calculated by dividing the total number of child features by the total number of parent features. A high average branching factor indicates a complex feature model with many options, while a low average branching factor indicates a simpler model.
69
+
70
+ * commonality: This is a measure of how often a feature appears in the products of a product line. It's usually expressed as a percentage. A feature with 100 per cent commonality is a core feature, as it appears in all products.
71
+
72
+ * configurations: These are the individual outcomes that can be produced from a feature model. Each product is a combination of features that satisfies all the constraints and dependencies in the feature model.
73
+
74
+ * configurations_number: This is the total number of different full configurations that can be produced from a feature model. It's calculated by considering all possible combinations of features, taking into account the constraints and dependencies between features.
75
+
76
+ * core_features: These are the features that are present in all products of a product line. In a feature model, they are the features that are mandatory and not optional. Core features define the commonality among all products in a product line. This call requires sat to be called, however, there is an implementation within flamapy that does not requires sat, please use the framework in case of needing it.
77
+
78
+ * count_leafs: This operation counts the number of leaf features in a feature model. Leaf features are those that do not have any child features. They represent the most specific options in a product line.
79
+ * dead_features: These are features that, due to the constraints and dependencies in the feature model, cannot be included in any valid product. Dead features are usually a sign of an error in the feature model.
80
+
81
+ * estimated_number_of_configurations: This is an estimate of the total number of different products that can be produced from a feature model. It's calculated by considering all possible combinations of features. This can be a simple multiplication if all
82
+ features are independent, but in most cases, constraints and dependencies between features need to be taken into account.
83
+
84
+ * false_optional_features: These are features that appear to be optional in the feature model, but due to the constraints and dependencies, must be included in every valid product. Like dead features, false optional features are usually a sign of an error in the feature model.
85
+
86
+ * feature_ancestors: These are the features that are directly or indirectly the parent of a given feature in a feature model. Ancestors of a feature are found by traversing up the feature hierarchy. This information can be useful to understand the context and dependencies of a feature.
87
+
88
+ * filter: This operation selects a subset of the products of a product line based on certain criteria. For example, youmight filter the products to only include those that contain a certain feature.
89
+
90
+ * leaf_features: This operation is used to find leaf features in a model: It returns the leaf features if they are found in themodel. If the model does not follow the UVL specification, an exception is raised and the operation returns False.
91
+
92
+ * max_depth: This operation is used to find the max depth of the tree in a model: It returns the max depth of the tree. If the model does not follow the UVL specification, an exception is raised and the operation returns False.
93
+
94
+ * satisfiable: In the context of feature models, this usually refers to whether the feature model itself satisfies all the
95
+ constraints and dependencies. A a valid feature model is one that does encodes at least a single valid product.
96
+
97
+ * satisfiable_configuration: This is a product that is produced from a valid configuration of features. A valid product satisfies all the constraints and dependencies in the feature model.
98
+
99
+
100
+
@@ -0,0 +1,82 @@
1
+ <div align="center">
2
+
3
+ <a href="">[![Pytest Testing Suite](https://github.com/flamapy/flamapy/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/flamapy/flamapy/actions/workflows/tests.yml)</a>
4
+ <a href="">[![Commits Syntax Checker](https://github.com/flamapy/flamapy/actions/workflows/commits.yml/badge.svg?branch=main)](https://github.com/flamapy/flamapy/actions/workflows/commits.yml)</a>
5
+ <a href="">![PyPI](https://img.shields.io/pypi/v/flamapy?label=pypi%20package)
6
+ <a href="">![PyPI - Downloads](https://img.shields.io/pypi/dm/flamapy)
7
+ </div>
8
+
9
+ #
10
+
11
+ <div id="top"></div>
12
+ <br />
13
+ <div align="center">
14
+
15
+ <h3 align="center">FLAMAPY</h3>
16
+
17
+ <p align="center">
18
+ A new and easy way to use FLAMA
19
+ <br />
20
+ <a href="https://github.com/flamapy/flamapy/issues">Report Bug</a>
21
+ ·
22
+ <a href="https://github.com/flamapy/flamapy/issues">Request Feature</a>
23
+ </p>
24
+ </div>
25
+ <!-- ABOUT THE PROJECT -->
26
+
27
+ # About The Project
28
+ FLAMAPY Feature model distribution provides an easier way of using FLAMAPY when analysing feature models. It packs the most used plugins for analyis of feature models adding a layer of convenience to use the framework or integrate it. If some other operations are required please see in the [documentation](flamapy.github.io/docs) if its supported in the ecosystem though the Python interface.
29
+
30
+ Feature Model Analysis has a crucial role in software product line engineering, enabling us to understand, design, and validate the complex relationships among features in a software product line. These feature models can often be complex and challenging to analyze due to their variability, making it difficult to identify conflicts, dead features, and potential optimizations. This is where this distribution comes in.
31
+
32
+ # Using the CMD
33
+ ```bash
34
+ flamapy --help #This will show the commands available
35
+ flamapy satisfiable <path to file> to check if a model is valid
36
+ ...
37
+ ```
38
+ # Using the Python interface
39
+ This is simple, Flama FM dist in hosted in pypi, therefore simply add the package flama-fm-dist to your requirements file and call the API as follows:
40
+
41
+ ```python
42
+ from flamapy.interfaces.python.flama_feature_model import FLAMAFeatureModel
43
+
44
+ fm = FLAMAFeatureModel("path/to/feature/model")
45
+ print(fm.valid())
46
+ ```
47
+ # Operations available:
48
+ Currently this distribution offers a subset of the operations available in the ecosystem, in the case of the feature mdoel distribution, we provide those operations that are well tested and used by the community. Nonetheless, If other more complex operations are required you can rely on the python interface of the framework to execute them all.
49
+
50
+ * atomic_sets: This operation is used to find the atomic sets in a model: It returns the atomic sets if they are found in the model. If the model does not follow the UVL specification, an exception is raised and the operation returns False.
51
+
52
+ * average_branching_factor:This refers to the average number of child features that a parent feature has in a feature model. It's calculated by dividing the total number of child features by the total number of parent features. A high average branching factor indicates a complex feature model with many options, while a low average branching factor indicates a simpler model.
53
+
54
+ * commonality: This is a measure of how often a feature appears in the products of a product line. It's usually expressed as a percentage. A feature with 100 per cent commonality is a core feature, as it appears in all products.
55
+
56
+ * configurations: These are the individual outcomes that can be produced from a feature model. Each product is a combination of features that satisfies all the constraints and dependencies in the feature model.
57
+
58
+ * configurations_number: This is the total number of different full configurations that can be produced from a feature model. It's calculated by considering all possible combinations of features, taking into account the constraints and dependencies between features.
59
+
60
+ * core_features: These are the features that are present in all products of a product line. In a feature model, they are the features that are mandatory and not optional. Core features define the commonality among all products in a product line. This call requires sat to be called, however, there is an implementation within flamapy that does not requires sat, please use the framework in case of needing it.
61
+
62
+ * count_leafs: This operation counts the number of leaf features in a feature model. Leaf features are those that do not have any child features. They represent the most specific options in a product line.
63
+ * dead_features: These are features that, due to the constraints and dependencies in the feature model, cannot be included in any valid product. Dead features are usually a sign of an error in the feature model.
64
+
65
+ * estimated_number_of_configurations: This is an estimate of the total number of different products that can be produced from a feature model. It's calculated by considering all possible combinations of features. This can be a simple multiplication if all
66
+ features are independent, but in most cases, constraints and dependencies between features need to be taken into account.
67
+
68
+ * false_optional_features: These are features that appear to be optional in the feature model, but due to the constraints and dependencies, must be included in every valid product. Like dead features, false optional features are usually a sign of an error in the feature model.
69
+
70
+ * feature_ancestors: These are the features that are directly or indirectly the parent of a given feature in a feature model. Ancestors of a feature are found by traversing up the feature hierarchy. This information can be useful to understand the context and dependencies of a feature.
71
+
72
+ * filter: This operation selects a subset of the products of a product line based on certain criteria. For example, youmight filter the products to only include those that contain a certain feature.
73
+
74
+ * leaf_features: This operation is used to find leaf features in a model: It returns the leaf features if they are found in themodel. If the model does not follow the UVL specification, an exception is raised and the operation returns False.
75
+
76
+ * max_depth: This operation is used to find the max depth of the tree in a model: It returns the max depth of the tree. If the model does not follow the UVL specification, an exception is raised and the operation returns False.
77
+
78
+ * satisfiable: In the context of feature models, this usually refers to whether the feature model itself satisfies all the
79
+ constraints and dependencies. A a valid feature model is one that does encodes at least a single valid product.
80
+
81
+ * satisfiable_configuration: This is a product that is produced from a valid configuration of features. A valid product satisfies all the constraints and dependencies in the feature model.
82
+
@@ -0,0 +1,168 @@
1
+ import argparse
2
+ import os
3
+ import sys
4
+ from functools import wraps
5
+ import inspect
6
+ from pathlib import Path
7
+ from shutil import copytree
8
+ from typing import List, Tuple, Optional
9
+ from types import FunctionType
10
+
11
+ from flamapy.interfaces.python.flamapy_feature_model import FLAMAFeatureModel
12
+ # List to store registered commands and their arguments
13
+ MANUAL_COMMANDS = []
14
+
15
+
16
+ def command(name, description, *args): # type: ignore
17
+
18
+ def decorator(func): # type: ignore
19
+ MANUAL_COMMANDS.append((name, description, func, args))
20
+
21
+ @wraps(func)
22
+ def wrapper(*func_args, **func_kwargs): # type: ignore
23
+ return func(*func_args, **func_kwargs)
24
+ return wrapper
25
+ return decorator
26
+
27
+
28
+ def extract_commands(cls: type) -> List[Tuple[str, str, FunctionType, List[inspect.Parameter]]]:
29
+ commands = []
30
+ for name, method in inspect.getmembers(cls, predicate=inspect.isfunction):
31
+ if name.startswith("_"):
32
+ continue
33
+ docstring: Optional[str] = method.__doc__
34
+ signature = inspect.signature(method)
35
+ # Exclude 'self' from parameters
36
+ parameters = list(signature.parameters.values())[1:] # Skip 'self'
37
+ commands.append((name, docstring or "", method, parameters))
38
+ return commands
39
+
40
+
41
+ @command('generate_plugin', """This command generates a new plugin to implement your
42
+ 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
+ def generate_plugin(args): # type: ignore
48
+ name = args.name
49
+ ext = args.extension
50
+ dst = args.path
51
+ src = 'skel_metamodel/'
52
+
53
+ # Check DST exist
54
+ if not os.path.isdir(dst):
55
+ print(f"Folder {dst} not exist")
56
+ sys.exit()
57
+
58
+ # Check DST is empty
59
+ if len(os.listdir(dst)) != 0:
60
+ print(f"Folder {dst} is not empty")
61
+ sys.exit()
62
+
63
+ # Check DST has permissions to WRITE
64
+ if not os.access(dst, os.W_OK):
65
+ print(f"Folder {dst} has not write permissions")
66
+ sys.exit()
67
+
68
+ # Generating structure
69
+ print("Generating structure ...")
70
+
71
+ copy_files = copytree(src, dst, dirs_exist_ok=True)
72
+
73
+ for copy_file in Path(copy_files).glob('**/*'):
74
+ if copy_file.is_dir():
75
+ continue
76
+ with open(copy_file, "r", encoding="utf-8") as file:
77
+ lines = file.readlines()
78
+ with open(copy_file, "w", encoding="utf-8") as filewrite:
79
+ for line in lines:
80
+ out_line = line.replace('__NAME__', name.capitalize()).replace('__EXT__', ext)
81
+ filewrite.write(out_line)
82
+
83
+ os.rename(os.path.join(dst, 'flamapy/metamodels/__NAME__'),
84
+ os.path.join(dst, f'flamapy/metamodels/{name}'))
85
+ print("Plugin generated!")
86
+
87
+
88
+ def setup_dynamic_commands(subparsers, dynamic_commands): # type: ignore
89
+ for name, docstring, method, parameters in dynamic_commands:
90
+ 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)
97
+ for param in parameters:
98
+ arg_name = param.name
99
+ if arg_name not in ['model_path']: # Avoid duplicates
100
+ if param.default == param.empty: # Positional argument
101
+ subparser.add_argument(arg_name,
102
+ type=param.annotation,
103
+ help=param.annotation.__name__)
104
+ 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__}')
109
+ subparser.set_defaults(func=method, method_name=name, parameters=parameters)
110
+
111
+
112
+ def setup_manual_commands(subparsers, manual_commands): # type: ignore
113
+ for name, description, func, args in manual_commands:
114
+ subparser = subparsers.add_parser(name, help=description)
115
+ for arg in args:
116
+ arg_name, arg_type, arg_help = arg
117
+ subparser.add_argument(arg_name, type=arg_type, help=arg_help)
118
+ subparser.set_defaults(func=func)
119
+
120
+
121
+ def execute_command(args: argparse.Namespace) -> None:
122
+ try:
123
+ if hasattr(args, 'method_name'):
124
+ cls_instance = FLAMAFeatureModel(args.model_path)
125
+ method_parameters = [param.name for param in args.parameters]
126
+ command_args = {k: v for k, v in vars(args).items() if k in method_parameters}
127
+ method = getattr(cls_instance, args.method_name)
128
+ result = method(**command_args)
129
+ if result is not None:
130
+ print(result)
131
+ else:
132
+ func = args.func
133
+ command_args = {k: v for k, v in vars(args).items() if k != 'func'}
134
+ result = func(args)
135
+ if result is not None:
136
+ print(result)
137
+ except FileNotFoundError as fnf_error:
138
+ print(f"File not found error: {fnf_error}")
139
+ except TypeError as type_error:
140
+ print(f"Type error: {type_error}")
141
+ except ValueError as value_error:
142
+ print(f"Value error: {value_error}")
143
+ except KeyError as key_error:
144
+ print(f"Key error: {key_error}")
145
+ except AttributeError as attr_error:
146
+ print(f"Attribute error: {attr_error}")
147
+
148
+
149
+ def flamapy_cli() -> None:
150
+ parser = argparse.ArgumentParser(description='FLAMA Feature Model CLI')
151
+ subparsers = parser.add_subparsers(dest='command')
152
+
153
+ dynamic_commands = extract_commands(FLAMAFeatureModel)
154
+ setup_dynamic_commands(subparsers, dynamic_commands)
155
+ setup_manual_commands(subparsers, MANUAL_COMMANDS)
156
+
157
+ args = parser.parse_args()
158
+
159
+ if args.command:
160
+ execute_command(args)
161
+ else:
162
+ print("Feature model operations:")
163
+ for name, docstring, _, _ in dynamic_commands:
164
+ print(f" {name}: {docstring}")
165
+ print("Framework developers operations:")
166
+ for name, description, _, _ in MANUAL_COMMANDS:
167
+ print(f" {name}: {description}")
168
+ print("Execute flamapy --help for more information")
@@ -0,0 +1,5 @@
1
+ from .flamapy_feature_model import (
2
+ FLAMAFeatureModel
3
+ )
4
+
5
+ __all__ = ['FLAMAFeatureModel']
@@ -1,47 +1,44 @@
1
+ from typing import List, Any, Union
1
2
  from flamapy.core.discover import DiscoverMetamodels
2
3
  from flamapy.metamodels.fm_metamodel.models import FeatureModel
3
- from typing import Optional
4
+ from flamapy.core.exceptions import FlamaException
5
+ from flamapy.metamodels.configuration_metamodel.models import Configuration
4
6
 
5
- class FLAMAFeatureModel():
6
7
 
7
- def __init__(self, model_path:str, configuration_path:Optional[str]=None):
8
+ class FLAMAFeatureModel:
9
+
10
+ def __init__(self, model_path: str):
8
11
  """
9
12
  This is the path in the filesystem where the model is located.
10
13
  Any model in UVL, FaMaXML or FeatureIDE format are accepted
11
14
  """
12
- self.model_path=model_path
13
- """
14
- This is the path in the filesystem where the configuration is located.
15
- Only CSV format are accepted (see documentation for more information)
16
- """
17
- self.configuration_path=configuration_path
15
+ self.model_path = model_path
18
16
  """
19
17
  Creating the interface witht he flama framework
20
18
  """
21
- self.dm = DiscoverMetamodels()
19
+ self.discover_metamodel = DiscoverMetamodels()
22
20
  """
23
21
  We save the model for later ussage
24
22
  """
25
- self.fm_model=self._read(model_path)
23
+ self.fm_model = self._read(model_path)
26
24
  """
27
25
  We create a empty sat model and a bdd model to avoid double transformations
28
26
  """
29
- self.sat_model=None
30
- self.bdd_model=None
27
+ self.sat_model = None
28
+ self.bdd_model = None
31
29
 
30
+ def _read(self, model_path: str) -> FeatureModel:
31
+ return self.discover_metamodel.use_transformation_t2m(model_path, 'fm')
32
32
 
33
- def _read(self, model_path)->FeatureModel:
34
- return self.dm.use_transformation_t2m(model_path,'fm')
35
-
36
- def _transform_to_sat(self):
33
+ def _transform_to_sat(self) -> None:
37
34
  if self.sat_model is None:
38
- self.sat_model=self.dm.use_transformation_m2m(self.fm_model,"pysat")
39
-
40
- def _transform_to_bdd(self):
35
+ self.sat_model = self.discover_metamodel.use_transformation_m2m(self.fm_model, "pysat")
36
+
37
+ def _transform_to_bdd(self) -> None:
41
38
  if self.bdd_model is None:
42
- self.bdd_model=self.dm.use_transformation_m2m(self.fm_model,"bdd")
39
+ self.bdd_model = self.discover_metamodel.use_transformation_m2m(self.fm_model, "bdd")
43
40
 
44
- def atomic_sets(self):
41
+ def atomic_sets(self) -> Union[None, List[List[Any]]]:
45
42
  """
46
43
  This operation is used to find the atomic sets in a model:
47
44
  It returns the atomic sets if they are found in the model.
@@ -51,7 +48,8 @@ class FLAMAFeatureModel():
51
48
 
52
49
  # Try to use the Find operation, which returns the atomic sets if they are found
53
50
  try:
54
- atomic_sets = self.dm.use_operation(self.fm_model,'FMAtomicSets').get_result()
51
+ atomic_sets = self.discover_metamodel.use_operation(self.fm_model,
52
+ 'FMAtomicSets').get_result()
55
53
  result = []
56
54
  for atomic_set in atomic_sets:
57
55
  partial_set = []
@@ -59,12 +57,11 @@ class FLAMAFeatureModel():
59
57
  partial_set.append(feature.name)
60
58
  result.append(partial_set)
61
59
  return result
62
- except Exception as e:
63
- print(f"Error: {e}")
60
+ except FlamaException as exception:
61
+ print(f"Error: {exception}")
64
62
  return None
65
63
 
66
-
67
- def average_branching_factor(self):
64
+ def average_branching_factor(self) -> Union[None, float]:
68
65
  """
69
66
  This refers to the average number of child features that a parent feature has in a
70
67
  feature model. It's calculated by dividing the total number of child features by the
@@ -75,14 +72,14 @@ class FLAMAFeatureModel():
75
72
 
76
73
  # Try to use the Find operation, which returns the atomic sets if they are found
77
74
  try:
78
- result = self.dm.use_operation(self.fm_model,'FMAverageBranchingFactor').get_result()
75
+ result = self.discover_metamodel.use_operation(self.fm_model,
76
+ 'FMAverageBranchingFactor').get_result()
79
77
  return result
80
- except Exception as e:
81
- print(f"Error: {e}")
78
+ except FlamaException as exception:
79
+ print(f"Error: {exception}")
82
80
  return None
83
81
 
84
-
85
- def count_leafs(self):
82
+ def count_leafs(self) -> Union[None, int]:
86
83
  """
87
84
  This operation counts the number of leaf features in a feature model. Leaf features
88
85
  are those that do not have any child features. They represent the most specific
@@ -91,14 +88,14 @@ class FLAMAFeatureModel():
91
88
 
92
89
  # Try to use the Find operation, which returns the atomic sets if they are found
93
90
  try:
94
- result = self.dm.use_operation(self.fm_model,'FMCountLeafs').get_result()
91
+ result = self.discover_metamodel.use_operation(self.fm_model,
92
+ 'FMCountLeafs').get_result()
95
93
  return result
96
- except Exception as e:
97
- print(f"Error: {e}")
94
+ except FlamaException as exception:
95
+ print(f"Error: {exception}")
98
96
  return None
99
97
 
100
-
101
- def estimated_number_of_configurations(self):
98
+ def estimated_number_of_configurations(self) -> Union[None, int]:
102
99
  """
103
100
  This is an estimate of the total number of different products that can be produced
104
101
  from a feature model. It's calculated by considering all possible combinations of
@@ -109,14 +106,14 @@ class FLAMAFeatureModel():
109
106
 
110
107
  # Try to use the Find operation, which returns the atomic sets if they are found
111
108
  try:
112
- result = self.dm.use_operation(self.fm_model,'FMEstimatedConfigurationsNumber').get_result()
109
+ result = self.discover_metamodel.use_operation(
110
+ self.fm_model, 'FMEstimatedConfigurationsNumber').get_result()
113
111
  return result
114
- except Exception as e:
115
- print(f"Error: {e}")
112
+ except FlamaException as exception:
113
+ print(f"Error: {exception}")
116
114
  return None
117
115
 
118
-
119
- def feature_ancestors(self,feature_name:str):
116
+ def feature_ancestors(self, feature_name: str) -> Union[None, List[str]]:
120
117
  '''
121
118
  These are the features that are directly or indirectly the parent of a given feature in
122
119
  a feature model. Ancestors of a feature are found by traversing up the feature hierarchy.
@@ -124,7 +121,7 @@ class FLAMAFeatureModel():
124
121
  '''
125
122
  # Try to use the Find operation, which returns the atomic sets if they are found
126
123
  try:
127
- operation = self.dm.get_operation(self.fm_model,'FMFeatureAncestors')
124
+ operation = self.discover_metamodel.get_operation(self.fm_model, 'FMFeatureAncestors')
128
125
  operation.set_feature(self.fm_model.get_feature_by_name(feature_name))
129
126
  operation.execute(self.fm_model)
130
127
  flama_result = operation.get_result()
@@ -132,38 +129,36 @@ class FLAMAFeatureModel():
132
129
  for res in flama_result:
133
130
  result.append(res.name)
134
131
  return result
135
- except Exception as e:
136
- print(f"Error: {e}")
132
+ except FlamaException as exception:
133
+ print(f"Error: {exception}")
137
134
  return None
138
135
 
139
-
140
-
141
- def leaf_features(self):
136
+ def leaf_features(self) -> Union[None, List[str]]:
142
137
  """
143
138
  This operation is used to find leaf features in a model:
144
139
  It returns the leaf features if they are found in the model.
145
140
  If the model does not follow the UVL specification, an
146
141
  exception is raised and the operation returns False.
147
-
142
+
148
143
  Traditionally you would use the flama tool by
149
- features = dm.use_operation_from_file('OperationString', model)
144
+ features = discover_metamodel.use_operation_from_file('OperationString', model)
150
145
  however, in this tool we know that this operation is from the fm metamodel,
151
146
  so we avoid to execute the transformation if possible
152
147
  """
153
148
 
154
149
  # Try to use the operation, which returns the leaf features if they are found
155
150
  try:
156
- features = self.dm.use_operation(self.fm_model,'FMLeafFeatures').get_result()
151
+ features = self.discover_metamodel.use_operation(self.fm_model,
152
+ 'FMLeafFeatures').get_result()
157
153
  leaf_features = []
158
154
  for feature in features:
159
155
  leaf_features.append(feature.name)
160
156
  return leaf_features
161
- except Exception as e:
162
- print(f"Error: {e}")
157
+ except FlamaException as exception:
158
+ print(f"Error: {exception}")
163
159
  return None
164
160
 
165
-
166
- def max_depth(self):
161
+ def max_depth(self) -> Union[None, int]:
167
162
  """
168
163
  This operation is used to find the max depth of the tree in a model:
169
164
  It returns the max depth of the tree.
@@ -173,32 +168,31 @@ class FLAMAFeatureModel():
173
168
 
174
169
  # Try to use the Find operation, which returns the max depth of the tree
175
170
  try:
176
- return self.dm.use_operation(self.fm_model,'FMMaxDepthTree').get_result()
177
- except Exception as e:
178
- print(f"Error: {e}")
171
+ return self.discover_metamodel.use_operation(self.fm_model,
172
+ 'FMMaxDepthTree').get_result()
173
+ except FlamaException as exception:
174
+ print(f"Error: {exception}")
179
175
  return None
180
176
 
181
- """
182
- The methods above rely on sat to be executed.
183
- """
184
-
185
- def core_features(self):
177
+ #The methods above rely on sat to be executed.
178
+ def core_features(self) -> Union[None, List[str]]:
186
179
  """
187
- These are the features that are present in all products of a product line. In a feature model,
188
- they are the features that are mandatory and not optional. Core features define the commonality
189
- among all products in a product line. This call requires sat to be called, however, there is
190
- an implementation within flama that does not requires sat. please use the framework in case of needing it.
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.
183
+ 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.
191
185
  """
192
186
  try:
193
187
  self._transform_to_sat()
194
- features = self.dm.use_operation(self.sat_model,'PySATCoreFeatures').get_result()
188
+ features = self.discover_metamodel.use_operation(self.sat_model,
189
+ 'PySATCoreFeatures').get_result()
195
190
  return features
196
- except Exception as e:
197
- print(f"Error: {e}")
191
+ except FlamaException as exception:
192
+ print(f"Error: {exception}")
198
193
  return None
199
194
 
200
-
201
- def dead_features(self):
195
+ def dead_features(self) -> Union[None, List[str]]:
202
196
  """
203
197
  These are features that, due to the constraints and dependencies in the
204
198
  feature model, cannot be included in any valid product. Dead features are usually
@@ -206,14 +200,14 @@ class FLAMAFeatureModel():
206
200
  """
207
201
  try:
208
202
  self._transform_to_sat()
209
- features = self.dm.use_operation(self.sat_model,'PySATDeadFeatures').get_result()
203
+ features = self.discover_metamodel.use_operation(self.sat_model,
204
+ 'PySATDeadFeatures').get_result()
210
205
  return features
211
- except Exception as e:
212
- print(f"Error: {e}")
206
+ except FlamaException as exception:
207
+ print(f"Error: {exception}")
213
208
  return None
214
209
 
215
-
216
- def false_optional_features(self):
210
+ def false_optional_features(self) -> Union[None, List[str]]:
217
211
  """
218
212
  These are features that appear to be optional in the feature model, but due to the
219
213
  constraints and dependencies, must be included in every valid product. Like dead features,
@@ -221,120 +215,128 @@ class FLAMAFeatureModel():
221
215
  """
222
216
  try:
223
217
  self._transform_to_sat()
224
-
225
- operation = self.dm.get_operation(self.sat_model,'PySATFalseOptionalFeatures')
226
- operation.feature_model=self.fm_model
218
+ operation = self.discover_metamodel.get_operation(self.sat_model,
219
+ 'PySATFalseOptionalFeatures')
220
+ operation.feature_model = self.fm_model
227
221
  operation.execute(self.sat_model)
228
222
  features = operation.get_result()
229
223
  return features
230
- except Exception as e:
231
- print(f"Error: {e}")
224
+ except FlamaException as exception:
225
+ print(f"Error: {exception}")
232
226
  return None
233
227
 
234
-
235
- def filter(self, configurationPath:str):
228
+ def filter(self, configuration_path: str) -> Union[None, List[Configuration]]:
236
229
  """
237
- This operation selects a subset of the products of a product line based on certain criteria.
238
- For example, you might filter the products to only include those that contain a certain feature.
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
232
+ contain a certain feature.
239
233
  """
240
234
  try:
241
235
  self._transform_to_sat()
242
- configuration = self.dm.use_transformation_t2m(configurationPath,'configuration')
243
-
244
- operation = self.dm.get_operation(self.sat_model,'PySATFilter')
236
+ configuration = self.discover_metamodel.use_transformation_t2m(configuration_path,
237
+ 'configuration')
238
+ operation = self.discover_metamodel.get_operation(self.sat_model, 'PySATFilter')
245
239
  operation.set_configuration(configuration)
246
240
  operation.execute(self.sat_model)
247
241
  result = operation.get_result()
248
242
  return result
249
- except Exception as e:
250
- print(f"Error: {e}")
243
+ except FlamaException as exception:
244
+ print(f"Error: {exception}")
251
245
  return None
252
246
 
253
-
254
- def configurations_number(self, with_sat:bool=False):
247
+ def configurations_number(self, with_sat: bool = False) -> Union[None, int]:
255
248
  """
256
- This is the total number of different full configurations that can be produced from a feature model.
257
- It's calculated by considering all possible combinations of features, taking into account
258
- the constraints and dependencies between features.
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
252
+ dependencies between features.
259
253
  """
260
254
  try:
261
- nop=0
255
+ nop = 0
262
256
  if with_sat:
263
257
  self._transform_to_sat()
264
- nop = self.dm.use_operation(self.sat_model,'PySATConfigurationsNumber').get_result()
265
-
258
+ nop = self.discover_metamodel.use_operation(
259
+ self.sat_model, 'PySATConfigurationsNumber'
260
+ ).get_result()
266
261
  else:
267
262
  self._transform_to_bdd()
268
- nop = self.dm.use_operation(self.bdd_model,'BDDConfigurationsNumber').get_result()
263
+ nop = self.discover_metamodel.use_operation(
264
+ self.bdd_model, 'BDDConfigurationsNumber'
265
+ ).get_result()
269
266
  return nop
270
- except Exception as e:
271
- print(f"Error: {e}")
267
+ except FlamaException as exception:
268
+ print(f"Error: {exception}")
272
269
  return None
273
270
 
274
-
275
- def configurations(self, with_sat:bool=False):
271
+ def configurations(self, with_sat: bool = False) -> Union[None, List[Configuration]]:
276
272
  """
277
273
  These are the individual outcomes that can be produced from a feature model. Each product
278
274
  is a combination of features that satisfies all the constraints and dependencies in the
279
275
  feature model.
280
276
  """
281
277
  try:
282
- products=[]
278
+ products = []
283
279
  if with_sat:
284
280
  self._transform_to_sat()
285
- products = self.dm.use_operation(self.sat_model,'PySATConfigurations').get_result()
281
+ products = self.discover_metamodel.use_operation(self.sat_model,
282
+ 'PySATConfigurations'
283
+ ).get_result()
286
284
  else:
287
285
  self._transform_to_bdd()
288
- products = self.dm.use_operation(self.bdd_model,'BDDConfigurations').get_result()
286
+ products = self.discover_metamodel.use_operation(self.bdd_model,
287
+ 'BDDConfigurations'
288
+ ).get_result()
289
289
  return products
290
- except Exception as e:
291
- print(f"Error: {e}")
290
+ except FlamaException as exception:
291
+ print(f"Error: {exception}")
292
292
  return None
293
293
 
294
-
295
- def commonality(self, configurationPath:str):
294
+ def commonality(self, configuration_path: str) -> Union[None, float]:
296
295
  """
297
296
  This is a measure of how often a feature appears in the products of a
298
297
  product line. It's usually expressed as a percentage. A feature with
299
- 100% commonality is a core feature, as it appears in all products.
298
+ 100 per cent commonality is a core feature, as it appears in all products.
300
299
  """
301
300
  try:
302
301
  self._transform_to_sat()
303
- configuration = self.dm.use_transformation_t2m(configurationPath,'configuration')
302
+ configuration = self.discover_metamodel.use_transformation_t2m(configuration_path,
303
+ 'configuration')
304
304
 
305
- operation = self.dm.get_operation(self.sat_model,'PySATCommonality')
305
+ operation = self.discover_metamodel.get_operation(self.sat_model, 'PySATCommonality')
306
306
  operation.set_configuration(configuration)
307
307
  operation.execute(self.sat_model)
308
308
  return operation.get_result()
309
- except Exception as e:
310
- print(f"Error: {e}")
309
+ except FlamaException as exception:
310
+ print(f"Error: {exception}")
311
311
  return None
312
312
 
313
-
314
- def satisfiable_configuration(self, configurationPath:str, full_configuration:bool=False):
313
+ def satisfiable_configuration(self,
314
+ configuration_path: str,
315
+ full_configuration: bool = False) -> Union[None, bool]:
315
316
  """
316
317
  This is a product that is produced from a valid configuration of features. A valid
317
318
  product satisfies all the constraints and dependencies in the feature model.
318
319
  """
319
320
  try:
320
321
  self._transform_to_sat()
321
- configuration = self.dm.use_transformation_t2m(configurationPath,'configuration')
322
- operation = self.dm.get_operation(self.sat_model,'PySATSatisfiableConfiguration')
323
- print(operation)
322
+ configuration = self.discover_metamodel.use_transformation_t2m(configuration_path,
323
+ 'configuration')
324
+ operation = self.discover_metamodel.get_operation(self.sat_model,
325
+ 'PySATSatisfiableConfiguration')
326
+
324
327
  if full_configuration:
325
328
  operation.set_configuration(configuration, is_full=True)
326
329
  else:
327
330
  operation.set_configuration(configuration, is_full=False)
328
-
331
+
329
332
  operation.execute(self.sat_model)
330
333
  result = operation.get_result()
331
334
  return result
332
- except Exception as e:
333
- print(f"Error: {e}")
335
+ except FlamaException as exception:
336
+ print(f"Error: {exception}")
334
337
  return None
335
338
 
336
-
337
- def satisfiable(self):
339
+ def satisfiable(self) -> Union[None, bool]:
338
340
  """
339
341
  In the context of feature models, this usually refers to whether the feature model itself
340
342
  satisfies all the constraints and dependencies. A a valid feature model is one that
@@ -342,10 +344,9 @@ class FLAMAFeatureModel():
342
344
  """
343
345
  try:
344
346
  self._transform_to_sat()
345
- result = self.dm.use_operation(self.sat_model,'PySATSatisfiable').get_result()
347
+ result = self.discover_metamodel.use_operation(self.sat_model,
348
+ 'PySATSatisfiable').get_result()
346
349
  return result
347
- except Exception as e:
348
- print(f"Error: {e}")
349
- return None
350
-
351
-
350
+ except FlamaException as exception:
351
+ print(f"Error: {exception}")
352
+ return None
@@ -0,0 +1,100 @@
1
+ Metadata-Version: 2.1
2
+ Name: flamapy
3
+ Version: 2.0.0.dev3
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
+ Home-page: https://github.com/flamapy/flamapy-feature-model
6
+ Author: Flamapy
7
+ Author-email: flamapy@us.es
8
+ License: UNKNOWN
9
+ Platform: UNKNOWN
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+ Provides-Extra: dev
16
+
17
+ <div align="center">
18
+
19
+ <a href="">[![Pytest Testing Suite](https://github.com/flamapy/flamapy/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/flamapy/flamapy/actions/workflows/tests.yml)</a>
20
+ <a href="">[![Commits Syntax Checker](https://github.com/flamapy/flamapy/actions/workflows/commits.yml/badge.svg?branch=main)](https://github.com/flamapy/flamapy/actions/workflows/commits.yml)</a>
21
+ <a href="">![PyPI](https://img.shields.io/pypi/v/flamapy?label=pypi%20package)
22
+ <a href="">![PyPI - Downloads](https://img.shields.io/pypi/dm/flamapy)
23
+ </div>
24
+
25
+ #
26
+
27
+ <div id="top"></div>
28
+ <br />
29
+ <div align="center">
30
+
31
+ <h3 align="center">FLAMAPY</h3>
32
+
33
+ <p align="center">
34
+ A new and easy way to use FLAMA
35
+ <br />
36
+ <a href="https://github.com/flamapy/flamapy/issues">Report Bug</a>
37
+ ·
38
+ <a href="https://github.com/flamapy/flamapy/issues">Request Feature</a>
39
+ </p>
40
+ </div>
41
+ <!-- ABOUT THE PROJECT -->
42
+
43
+ # About The Project
44
+ FLAMAPY Feature model distribution provides an easier way of using FLAMAPY when analysing feature models. It packs the most used plugins for analyis of feature models adding a layer of convenience to use the framework or integrate it. If some other operations are required please see in the [documentation](flamapy.github.io/docs) if its supported in the ecosystem though the Python interface.
45
+
46
+ Feature Model Analysis has a crucial role in software product line engineering, enabling us to understand, design, and validate the complex relationships among features in a software product line. These feature models can often be complex and challenging to analyze due to their variability, making it difficult to identify conflicts, dead features, and potential optimizations. This is where this distribution comes in.
47
+
48
+ # Using the CMD
49
+ ```bash
50
+ flamapy --help #This will show the commands available
51
+ flamapy satisfiable <path to file> to check if a model is valid
52
+ ...
53
+ ```
54
+ # Using the Python interface
55
+ This is simple, Flama FM dist in hosted in pypi, therefore simply add the package flama-fm-dist to your requirements file and call the API as follows:
56
+
57
+ ```python
58
+ from flamapy.interfaces.python.flama_feature_model import FLAMAFeatureModel
59
+
60
+ fm = FLAMAFeatureModel("path/to/feature/model")
61
+ print(fm.valid())
62
+ ```
63
+ # Operations available:
64
+ Currently this distribution offers a subset of the operations available in the ecosystem, in the case of the feature mdoel distribution, we provide those operations that are well tested and used by the community. Nonetheless, If other more complex operations are required you can rely on the python interface of the framework to execute them all.
65
+
66
+ * atomic_sets: This operation is used to find the atomic sets in a model: It returns the atomic sets if they are found in the model. If the model does not follow the UVL specification, an exception is raised and the operation returns False.
67
+
68
+ * average_branching_factor:This refers to the average number of child features that a parent feature has in a feature model. It's calculated by dividing the total number of child features by the total number of parent features. A high average branching factor indicates a complex feature model with many options, while a low average branching factor indicates a simpler model.
69
+
70
+ * commonality: This is a measure of how often a feature appears in the products of a product line. It's usually expressed as a percentage. A feature with 100 per cent commonality is a core feature, as it appears in all products.
71
+
72
+ * configurations: These are the individual outcomes that can be produced from a feature model. Each product is a combination of features that satisfies all the constraints and dependencies in the feature model.
73
+
74
+ * configurations_number: This is the total number of different full configurations that can be produced from a feature model. It's calculated by considering all possible combinations of features, taking into account the constraints and dependencies between features.
75
+
76
+ * core_features: These are the features that are present in all products of a product line. In a feature model, they are the features that are mandatory and not optional. Core features define the commonality among all products in a product line. This call requires sat to be called, however, there is an implementation within flamapy that does not requires sat, please use the framework in case of needing it.
77
+
78
+ * count_leafs: This operation counts the number of leaf features in a feature model. Leaf features are those that do not have any child features. They represent the most specific options in a product line.
79
+ * dead_features: These are features that, due to the constraints and dependencies in the feature model, cannot be included in any valid product. Dead features are usually a sign of an error in the feature model.
80
+
81
+ * estimated_number_of_configurations: This is an estimate of the total number of different products that can be produced from a feature model. It's calculated by considering all possible combinations of features. This can be a simple multiplication if all
82
+ features are independent, but in most cases, constraints and dependencies between features need to be taken into account.
83
+
84
+ * false_optional_features: These are features that appear to be optional in the feature model, but due to the constraints and dependencies, must be included in every valid product. Like dead features, false optional features are usually a sign of an error in the feature model.
85
+
86
+ * feature_ancestors: These are the features that are directly or indirectly the parent of a given feature in a feature model. Ancestors of a feature are found by traversing up the feature hierarchy. This information can be useful to understand the context and dependencies of a feature.
87
+
88
+ * filter: This operation selects a subset of the products of a product line based on certain criteria. For example, youmight filter the products to only include those that contain a certain feature.
89
+
90
+ * leaf_features: This operation is used to find leaf features in a model: It returns the leaf features if they are found in themodel. If the model does not follow the UVL specification, an exception is raised and the operation returns False.
91
+
92
+ * max_depth: This operation is used to find the max depth of the tree in a model: It returns the max depth of the tree. If the model does not follow the UVL specification, an exception is raised and the operation returns False.
93
+
94
+ * satisfiable: In the context of feature models, this usually refers to whether the feature model itself satisfies all the
95
+ constraints and dependencies. A a valid feature model is one that does encodes at least a single valid product.
96
+
97
+ * satisfiable_configuration: This is a product that is produced from a valid configuration of features. A valid product satisfies all the constraints and dependencies in the feature model.
98
+
99
+
100
+
@@ -6,6 +6,6 @@ flamapy.egg-info/dependency_links.txt
6
6
  flamapy.egg-info/entry_points.txt
7
7
  flamapy.egg-info/requires.txt
8
8
  flamapy.egg-info/top_level.txt
9
- flamapy/interfaces/__init__.py
10
- flamapy/interfaces/python/FLAMAFeatureModel.py
11
- flamapy/interfaces/python/__init__.py
9
+ flamapy/commands/__init__.py
10
+ flamapy/interfaces/python/__init__.py
11
+ flamapy/interfaces/python/flamapy_feature_model.py
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ flamapy = flamapy.commands:flamapy_cli
3
+
@@ -0,0 +1,12 @@
1
+ wheel
2
+ flamapy-fw==2.0.0.dev6
3
+ flamapy-fm==2.0.0.dev7
4
+ flamapy-sat==2.0.0.dev7
5
+ flamapy-bdd==2.0.0.dev9
6
+
7
+ [dev]
8
+ pytest
9
+ pytest-mock
10
+ prospector
11
+ mypy
12
+ coverage
@@ -16,7 +16,7 @@ dev_requirements = read_requirements("requirements-dev.txt")
16
16
 
17
17
  setuptools.setup(
18
18
  name="flamapy",
19
- version="2.0.0.dev2",
19
+ version="2.0.0.dev3",
20
20
  author="Flamapy",
21
21
  author_email="flamapy@us.es",
22
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.",
@@ -36,7 +36,7 @@ setuptools.setup(
36
36
  },
37
37
  entry_points={
38
38
  'console_scripts': [
39
- 'flamapy-fm-cli = flamapy.interfaces.command_line:flama_fm',
39
+ 'flamapy = flamapy.commands:flamapy_cli',
40
40
  ],
41
41
  },
42
42
  )
@@ -1,84 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: flamapy
3
- Version: 2.0.0.dev2
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
- Home-page: https://github.com/flamapy/flamapy-feature-model
6
- Author: Flamapy
7
- Author-email: flamapy@us.es
8
- License: UNKNOWN
9
- Platform: UNKNOWN
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
12
- Classifier: Operating System :: OS Independent
13
- Requires-Python: >=3.9
14
- Description-Content-Type: text/markdown
15
- Provides-Extra: dev
16
-
17
- <div align="center">
18
-
19
- <a href="">[![Pytest Testing Suite](https://github.com/flamapy/flamapy/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/flamapy/flamapy/actions/workflows/tests.yml)</a>
20
- <a href="">[![Commits Syntax Checker](https://github.com/flamapy/flamapy/actions/workflows/commits.yml/badge.svg?branch=main)](https://github.com/flamapy/flamapy/actions/workflows/commits.yml)</a>
21
- <a href="">![PyPI](https://img.shields.io/pypi/v/flamapy?label=pypi%20package)
22
- <a href="">![PyPI - Downloads](https://img.shields.io/pypi/dm/flamapy)
23
- </div>
24
-
25
- #
26
-
27
- <div id="top"></div>
28
- <br />
29
- <div align="center">
30
-
31
- <h3 align="center">FLAMAPY</h3>
32
-
33
- <p align="center">
34
- A new and easy way to use FLAMA
35
- <br />
36
- <a href="https://github.com/flamapy/flamapy/issues">Report Bug</a>
37
- ·
38
- <a href="https://github.com/flamapy/flamapy/issues">Request Feature</a>
39
- </p>
40
- </div>
41
- <!-- ABOUT THE PROJECT -->
42
-
43
- ## About The Project
44
-
45
- FLAMAPY Feature model distribution provides an easier way of using FLAMA when analysing feature models. It packs the most used plugins for analyis of feature models adding a layer of convenience to use the framework or integrate it.
46
-
47
- Feature Model Analysis has a crucial role in software product line engineering, enabling us to understand, design, and validate the complex relationships among features in a software product line. These feature models can often be complex and challenging to analyze due to their variability, making it difficult to identify conflicts, dead features, and potential optimizations. This is where this distribution comes in.
48
-
49
- # Soon comming, easy to use CMD
50
- ## TODO
51
-
52
- # Using the Python interface
53
- This is simple, Flama FM dist in hosted in pypi, therefore simply add the package flama-fm-dist to your requirements file and call the API as follows:
54
-
55
- ```python
56
- from flamapy.interfaces.python.FLAMAFeatureModel import FLAMAFeatureModel
57
-
58
- fm = FLAMAFeatureModel("path/to/feature/model")
59
- print(fm.valid())
60
- ```
61
- Currently the operations provided by this distribution are:
62
- * atomic_sets: This operation is used to find the atomic sets in a model. It returns the atomic sets if they are found in the model. If the model does not follow the UVL specification, an exception is raised and the operation returns False.
63
- * average_branching_factor: This refers to the average number of child features that a parent feature has in a feature model. It's calculated by dividing the total number of child features by the total number of parent features. A high average branching factor indicates a complex feature model with many options, while a low average branching factor indicates a simpler model.
64
- * count_leafs: This operation counts the number of leaf features in a feature model. Leaf features are those that do not have any child features. They represent the most specific options in a product line.
65
- * estimated_number_of_products: This is an estimate of the total number of different products that can be produced from a feature model. It's calculated by considering all possible combinations of features. This can be a simple multiplication if all features are independent, but in most cases, constraints and dependencies between features need to be taken into account.
66
- * feature_ancestors: These are the features that are directly or indirectly the parent of a given feature in a feature model. Ancestors of a feature are found by traversing up the feature hierarchy. This information can be useful to understand the context and dependencies of a feature.
67
- * leaf_features: This operation is used to find leaf features in a model. It returns the leaf features if they are found in the model. If the model does not follow the UVL specification, an
68
- exception is raised and the operation returns False.
69
- * max_dept: This operation is used to find the max depth of the tree in a model.It returns the max depth of the tree.
70
- * commonality: This is a measure of how often a feature appears in the products of a product line. It's usually expressed as a percentage. A feature with 100% commonality is a core feature, as it appears in all products.
71
- * core_features: These are the features that are present in all products of a product line. In a feature model, they are the features that are mandatory and not optional. Core features define the commonality among all products in a product line. This call requires sat to be called, however, there is an implementation within flama that does not requires sat. please use the framework in case of needing it.
72
- * dead_features: These are features that, due to the constraints and dependencies in the feature model, cannot be included in any valid product. Dead features are usually a sign of an error in the feature model.
73
- * error_detection: This refers to the process of identifying and locating errors in a feature model. Errors can include things like dead features, false optional features, or contradictions in the constraints.
74
- * false_optional_features: These are features that appear to be optional in the feature model, but due to the constraints and dependencies, must be included in every valid product. Like dead features, false optional features are usually a sign of an error in the feature model.
75
- * filter: This operation selects a subset of the products of a product line based on certain criteria. For example, you might filter the products to only include those that contain a certain feature.
76
- * products number: This is the total number of different products that can be produced from a feature model.It's calculated by considering all possible combinations of features, taking into account the constraints and dependencies between features.
77
- * products: This operation returns all the products of a product line. A product is a valid combination of features that can be produced from a feature model. The products are returned as a list of lists, where each inner list represents a product and contains the features that are included in that product.
78
- * valid_configuration: This operation checks if a given configuration is valid in a feature model. A configuration is a list of features that are included in a product. The operation returns True if the configuration is valid, and False if it's not.
79
- * valid_product: This operation checks if a given product (full configuration) is valid in a feature model. A product is a list of features that are included in a product. The operation returns True if the product is valid, and False if it's not.
80
- * valid: This operation checks if a feature model is valid. A feature model is valid if it follows the UVL specification. The operation returns True if the feature model is valid, and False if it's not.
81
-
82
-
83
-
84
-
@@ -1,66 +0,0 @@
1
- <div align="center">
2
-
3
- <a href="">[![Pytest Testing Suite](https://github.com/flamapy/flamapy/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/flamapy/flamapy/actions/workflows/tests.yml)</a>
4
- <a href="">[![Commits Syntax Checker](https://github.com/flamapy/flamapy/actions/workflows/commits.yml/badge.svg?branch=main)](https://github.com/flamapy/flamapy/actions/workflows/commits.yml)</a>
5
- <a href="">![PyPI](https://img.shields.io/pypi/v/flamapy?label=pypi%20package)
6
- <a href="">![PyPI - Downloads](https://img.shields.io/pypi/dm/flamapy)
7
- </div>
8
-
9
- #
10
-
11
- <div id="top"></div>
12
- <br />
13
- <div align="center">
14
-
15
- <h3 align="center">FLAMAPY</h3>
16
-
17
- <p align="center">
18
- A new and easy way to use FLAMA
19
- <br />
20
- <a href="https://github.com/flamapy/flamapy/issues">Report Bug</a>
21
- ·
22
- <a href="https://github.com/flamapy/flamapy/issues">Request Feature</a>
23
- </p>
24
- </div>
25
- <!-- ABOUT THE PROJECT -->
26
-
27
- ## About The Project
28
-
29
- FLAMAPY Feature model distribution provides an easier way of using FLAMA when analysing feature models. It packs the most used plugins for analyis of feature models adding a layer of convenience to use the framework or integrate it.
30
-
31
- Feature Model Analysis has a crucial role in software product line engineering, enabling us to understand, design, and validate the complex relationships among features in a software product line. These feature models can often be complex and challenging to analyze due to their variability, making it difficult to identify conflicts, dead features, and potential optimizations. This is where this distribution comes in.
32
-
33
- # Soon comming, easy to use CMD
34
- ## TODO
35
-
36
- # Using the Python interface
37
- This is simple, Flama FM dist in hosted in pypi, therefore simply add the package flama-fm-dist to your requirements file and call the API as follows:
38
-
39
- ```python
40
- from flamapy.interfaces.python.FLAMAFeatureModel import FLAMAFeatureModel
41
-
42
- fm = FLAMAFeatureModel("path/to/feature/model")
43
- print(fm.valid())
44
- ```
45
- Currently the operations provided by this distribution are:
46
- * atomic_sets: This operation is used to find the atomic sets in a model. It returns the atomic sets if they are found in the model. If the model does not follow the UVL specification, an exception is raised and the operation returns False.
47
- * average_branching_factor: This refers to the average number of child features that a parent feature has in a feature model. It's calculated by dividing the total number of child features by the total number of parent features. A high average branching factor indicates a complex feature model with many options, while a low average branching factor indicates a simpler model.
48
- * count_leafs: This operation counts the number of leaf features in a feature model. Leaf features are those that do not have any child features. They represent the most specific options in a product line.
49
- * estimated_number_of_products: This is an estimate of the total number of different products that can be produced from a feature model. It's calculated by considering all possible combinations of features. This can be a simple multiplication if all features are independent, but in most cases, constraints and dependencies between features need to be taken into account.
50
- * feature_ancestors: These are the features that are directly or indirectly the parent of a given feature in a feature model. Ancestors of a feature are found by traversing up the feature hierarchy. This information can be useful to understand the context and dependencies of a feature.
51
- * leaf_features: This operation is used to find leaf features in a model. It returns the leaf features if they are found in the model. If the model does not follow the UVL specification, an
52
- exception is raised and the operation returns False.
53
- * max_dept: This operation is used to find the max depth of the tree in a model.It returns the max depth of the tree.
54
- * commonality: This is a measure of how often a feature appears in the products of a product line. It's usually expressed as a percentage. A feature with 100% commonality is a core feature, as it appears in all products.
55
- * core_features: These are the features that are present in all products of a product line. In a feature model, they are the features that are mandatory and not optional. Core features define the commonality among all products in a product line. This call requires sat to be called, however, there is an implementation within flama that does not requires sat. please use the framework in case of needing it.
56
- * dead_features: These are features that, due to the constraints and dependencies in the feature model, cannot be included in any valid product. Dead features are usually a sign of an error in the feature model.
57
- * error_detection: This refers to the process of identifying and locating errors in a feature model. Errors can include things like dead features, false optional features, or contradictions in the constraints.
58
- * false_optional_features: These are features that appear to be optional in the feature model, but due to the constraints and dependencies, must be included in every valid product. Like dead features, false optional features are usually a sign of an error in the feature model.
59
- * filter: This operation selects a subset of the products of a product line based on certain criteria. For example, you might filter the products to only include those that contain a certain feature.
60
- * products number: This is the total number of different products that can be produced from a feature model.It's calculated by considering all possible combinations of features, taking into account the constraints and dependencies between features.
61
- * products: This operation returns all the products of a product line. A product is a valid combination of features that can be produced from a feature model. The products are returned as a list of lists, where each inner list represents a product and contains the features that are included in that product.
62
- * valid_configuration: This operation checks if a given configuration is valid in a feature model. A configuration is a list of features that are included in a product. The operation returns True if the configuration is valid, and False if it's not.
63
- * valid_product: This operation checks if a given product (full configuration) is valid in a feature model. A product is a list of features that are included in a product. The operation returns True if the product is valid, and False if it's not.
64
- * valid: This operation checks if a feature model is valid. A feature model is valid if it follows the UVL specification. The operation returns True if the feature model is valid, and False if it's not.
65
-
66
-
File without changes
File without changes
@@ -1,84 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: flamapy
3
- Version: 2.0.0.dev2
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
- Home-page: https://github.com/flamapy/flamapy-feature-model
6
- Author: Flamapy
7
- Author-email: flamapy@us.es
8
- License: UNKNOWN
9
- Platform: UNKNOWN
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
12
- Classifier: Operating System :: OS Independent
13
- Requires-Python: >=3.9
14
- Description-Content-Type: text/markdown
15
- Provides-Extra: dev
16
-
17
- <div align="center">
18
-
19
- <a href="">[![Pytest Testing Suite](https://github.com/flamapy/flamapy/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/flamapy/flamapy/actions/workflows/tests.yml)</a>
20
- <a href="">[![Commits Syntax Checker](https://github.com/flamapy/flamapy/actions/workflows/commits.yml/badge.svg?branch=main)](https://github.com/flamapy/flamapy/actions/workflows/commits.yml)</a>
21
- <a href="">![PyPI](https://img.shields.io/pypi/v/flamapy?label=pypi%20package)
22
- <a href="">![PyPI - Downloads](https://img.shields.io/pypi/dm/flamapy)
23
- </div>
24
-
25
- #
26
-
27
- <div id="top"></div>
28
- <br />
29
- <div align="center">
30
-
31
- <h3 align="center">FLAMAPY</h3>
32
-
33
- <p align="center">
34
- A new and easy way to use FLAMA
35
- <br />
36
- <a href="https://github.com/flamapy/flamapy/issues">Report Bug</a>
37
- ·
38
- <a href="https://github.com/flamapy/flamapy/issues">Request Feature</a>
39
- </p>
40
- </div>
41
- <!-- ABOUT THE PROJECT -->
42
-
43
- ## About The Project
44
-
45
- FLAMAPY Feature model distribution provides an easier way of using FLAMA when analysing feature models. It packs the most used plugins for analyis of feature models adding a layer of convenience to use the framework or integrate it.
46
-
47
- Feature Model Analysis has a crucial role in software product line engineering, enabling us to understand, design, and validate the complex relationships among features in a software product line. These feature models can often be complex and challenging to analyze due to their variability, making it difficult to identify conflicts, dead features, and potential optimizations. This is where this distribution comes in.
48
-
49
- # Soon comming, easy to use CMD
50
- ## TODO
51
-
52
- # Using the Python interface
53
- This is simple, Flama FM dist in hosted in pypi, therefore simply add the package flama-fm-dist to your requirements file and call the API as follows:
54
-
55
- ```python
56
- from flamapy.interfaces.python.FLAMAFeatureModel import FLAMAFeatureModel
57
-
58
- fm = FLAMAFeatureModel("path/to/feature/model")
59
- print(fm.valid())
60
- ```
61
- Currently the operations provided by this distribution are:
62
- * atomic_sets: This operation is used to find the atomic sets in a model. It returns the atomic sets if they are found in the model. If the model does not follow the UVL specification, an exception is raised and the operation returns False.
63
- * average_branching_factor: This refers to the average number of child features that a parent feature has in a feature model. It's calculated by dividing the total number of child features by the total number of parent features. A high average branching factor indicates a complex feature model with many options, while a low average branching factor indicates a simpler model.
64
- * count_leafs: This operation counts the number of leaf features in a feature model. Leaf features are those that do not have any child features. They represent the most specific options in a product line.
65
- * estimated_number_of_products: This is an estimate of the total number of different products that can be produced from a feature model. It's calculated by considering all possible combinations of features. This can be a simple multiplication if all features are independent, but in most cases, constraints and dependencies between features need to be taken into account.
66
- * feature_ancestors: These are the features that are directly or indirectly the parent of a given feature in a feature model. Ancestors of a feature are found by traversing up the feature hierarchy. This information can be useful to understand the context and dependencies of a feature.
67
- * leaf_features: This operation is used to find leaf features in a model. It returns the leaf features if they are found in the model. If the model does not follow the UVL specification, an
68
- exception is raised and the operation returns False.
69
- * max_dept: This operation is used to find the max depth of the tree in a model.It returns the max depth of the tree.
70
- * commonality: This is a measure of how often a feature appears in the products of a product line. It's usually expressed as a percentage. A feature with 100% commonality is a core feature, as it appears in all products.
71
- * core_features: These are the features that are present in all products of a product line. In a feature model, they are the features that are mandatory and not optional. Core features define the commonality among all products in a product line. This call requires sat to be called, however, there is an implementation within flama that does not requires sat. please use the framework in case of needing it.
72
- * dead_features: These are features that, due to the constraints and dependencies in the feature model, cannot be included in any valid product. Dead features are usually a sign of an error in the feature model.
73
- * error_detection: This refers to the process of identifying and locating errors in a feature model. Errors can include things like dead features, false optional features, or contradictions in the constraints.
74
- * false_optional_features: These are features that appear to be optional in the feature model, but due to the constraints and dependencies, must be included in every valid product. Like dead features, false optional features are usually a sign of an error in the feature model.
75
- * filter: This operation selects a subset of the products of a product line based on certain criteria. For example, you might filter the products to only include those that contain a certain feature.
76
- * products number: This is the total number of different products that can be produced from a feature model.It's calculated by considering all possible combinations of features, taking into account the constraints and dependencies between features.
77
- * products: This operation returns all the products of a product line. A product is a valid combination of features that can be produced from a feature model. The products are returned as a list of lists, where each inner list represents a product and contains the features that are included in that product.
78
- * valid_configuration: This operation checks if a given configuration is valid in a feature model. A configuration is a list of features that are included in a product. The operation returns True if the configuration is valid, and False if it's not.
79
- * valid_product: This operation checks if a given product (full configuration) is valid in a feature model. A product is a list of features that are included in a product. The operation returns True if the product is valid, and False if it's not.
80
- * valid: This operation checks if a feature model is valid. A feature model is valid if it follows the UVL specification. The operation returns True if the feature model is valid, and False if it's not.
81
-
82
-
83
-
84
-
@@ -1,3 +0,0 @@
1
- [console_scripts]
2
- flamapy-fm-cli = flamapy.interfaces.command_line:flama_fm
3
-
@@ -1,12 +0,0 @@
1
- wheel
2
- flamapy-fw==2.0.0.dev2
3
- flamapy-fm==2.0.0.dev2
4
- flamapy-sat==2.0.0.dev2
5
- flamapy-bdd==2.0.0.dev1
6
-
7
- [dev]
8
- pytest
9
- pytest-mock
10
- prospector
11
- mypy
12
- coverage
File without changes