flamapy 2.5.0.dev0__py3-none-any.whl → 2.6.0.dev0__py3-none-any.whl

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,5 +1,5 @@
1
1
  import logging
2
- from typing import List, Any, Union
2
+ from typing import Any, Dict, Generator, List, Optional, Tuple, Union
3
3
  from flamapy.core.discover import DiscoverMetamodels
4
4
  from flamapy.metamodels.fm_metamodel.models import FeatureModel
5
5
  from flamapy.core.exceptions import FlamaException
@@ -15,19 +15,12 @@ class FLAMAFeatureModel:
15
15
  Any model in UVL, FaMaXML or FeatureIDE format are accepted
16
16
  """
17
17
  self.model_path = model_path
18
- """
19
- Creating the interface witht he flama framework
20
- """
21
18
  self.discover_metamodel = DiscoverMetamodels()
22
- """
23
- We save the model for later ussage
24
- """
25
19
  self.fm_model = self._read(model_path)
26
- """
27
- We create a empty sat model and a bdd model to avoid double transformations
28
- """
29
20
  self.sat_model = None
30
21
  self.bdd_model = None
22
+ self.z3_model = None
23
+ self.diagnosis_model = None
31
24
 
32
25
  def _read(self, model_path: str) -> FeatureModel:
33
26
  return self.discover_metamodel.use_transformation_t2m(model_path, "fm")
@@ -40,6 +33,16 @@ class FLAMAFeatureModel:
40
33
  if self.bdd_model is None:
41
34
  self.bdd_model = self.discover_metamodel.use_transformation_m2m(self.fm_model, "bdd")
42
35
 
36
+ def _transform_to_z3(self) -> None:
37
+ if self.z3_model is None:
38
+ self.z3_model = self.discover_metamodel.use_transformation_m2m(self.fm_model, "z3")
39
+
40
+ def _transform_to_diagnosis(self) -> None:
41
+ if self.diagnosis_model is None:
42
+ self.diagnosis_model = self.discover_metamodel.use_transformation_m2m(
43
+ self.fm_model, "pysat_diagnosis"
44
+ )
45
+
43
46
  def atomic_sets(self) -> Union[None, List[List[Any]]]:
44
47
  """
45
48
  This operation is used to find the atomic sets in a model:
@@ -379,3 +382,286 @@ class FLAMAFeatureModel:
379
382
  except FlamaException as exception:
380
383
  logger.error("Error: %s", exception)
381
384
  return None
385
+
386
+ # FM-based operations
387
+
388
+ def metrics(self) -> Union[None, List[Dict[str, Any]]]:
389
+ """
390
+ Returns a collection of structural metrics for the feature model, such as number of
391
+ features, constraints, relations, and complexity indicators.
392
+ """
393
+ try:
394
+ return self.discover_metamodel.use_operation(
395
+ self.fm_model, "FMMetrics"
396
+ ).get_result()
397
+ except FlamaException as exception:
398
+ logger.error("Error: %s", exception)
399
+ return None
400
+
401
+ def variation_points(self) -> Union[None, Dict[str, List[str]]]:
402
+ """
403
+ Returns the variation points of the feature model. A variation point is a feature that
404
+ has at least one non-mandatory child, representing a decision point in the model.
405
+ The result maps each variation point name to the list of its variant feature names.
406
+ """
407
+ try:
408
+ raw = self.discover_metamodel.use_operation(
409
+ self.fm_model, "FMVariationPoints"
410
+ ).get_result()
411
+ return {vp.name: [v.name for v in variants] for vp, variants in raw.items()}
412
+ except FlamaException as exception:
413
+ logger.error("Error: %s", exception)
414
+ return None
415
+
416
+ # SAT-based operations
417
+
418
+ def backbone(self) -> Union[None, Dict[str, List[Any]]]:
419
+ """
420
+ Returns the backbone of the feature model: the set of features that must always be
421
+ selected (core) and those that must never be selected (dead) across all valid
422
+ configurations, grouped under 'core' and 'dead' keys.
423
+ """
424
+ try:
425
+ self._transform_to_sat()
426
+ return self.discover_metamodel.use_operation(
427
+ self.sat_model, "PySATBackbone"
428
+ ).get_result()
429
+ except FlamaException as exception:
430
+ logger.error("Error: %s", exception)
431
+ return None
432
+
433
+ # BDD-based operations
434
+
435
+ def homogeneity(self) -> Union[None, float]:
436
+ """
437
+ Measures how similar the products of the feature model are to each other. It is
438
+ computed as the average commonality factor across all features. A value of 1.0 means
439
+ all products are identical; lower values indicate more diversity.
440
+ """
441
+ try:
442
+ self._transform_to_bdd()
443
+ return self.discover_metamodel.use_operation(
444
+ self.bdd_model, "BDDHomogeneity"
445
+ ).get_result()
446
+ except FlamaException as exception:
447
+ logger.error("Error: %s", exception)
448
+ return None
449
+
450
+ def product_distribution(self) -> Union[None, List[int]]:
451
+ """
452
+ Returns the distribution of products by number of activated features. The value at
453
+ index i is the count of valid configurations that have exactly i features selected.
454
+ """
455
+ try:
456
+ self._transform_to_bdd()
457
+ return self.discover_metamodel.use_operation(
458
+ self.bdd_model, "BDDProductDistribution"
459
+ ).get_result()
460
+ except FlamaException as exception:
461
+ logger.error("Error: %s", exception)
462
+ return None
463
+
464
+ def variability(self) -> Union[None, Tuple[float, float]]:
465
+ """
466
+ Returns a tuple of (total_variability, partial_variability). Total variability is the
467
+ ratio of valid configurations to the theoretical maximum; partial variability is the
468
+ ratio relative to only the variant features.
469
+ """
470
+ try:
471
+ self._transform_to_bdd()
472
+ return self.discover_metamodel.use_operation(
473
+ self.bdd_model, "BDDVariability"
474
+ ).get_result()
475
+ except FlamaException as exception:
476
+ logger.error("Error: %s", exception)
477
+ return None
478
+
479
+ def variant_features(self) -> Union[None, List[str]]:
480
+ """
481
+ Returns the features that are neither core nor dead — they appear in some but not all
482
+ valid configurations. These are the features that actually vary across products.
483
+ """
484
+ try:
485
+ self._transform_to_bdd()
486
+ return self.discover_metamodel.use_operation(
487
+ self.bdd_model, "BDDVariantFeatures"
488
+ ).get_result()
489
+ except FlamaException as exception:
490
+ logger.error("Error: %s", exception)
491
+ return None
492
+
493
+ def unique_features(self) -> Union[None, List[str]]:
494
+ """
495
+ Returns features that appear in exactly one valid configuration. These features
496
+ uniquely identify a single product in the product line.
497
+ """
498
+ try:
499
+ self._transform_to_bdd()
500
+ return self.discover_metamodel.use_operation(
501
+ self.bdd_model, "BDDUniqueFeatures"
502
+ ).get_result()
503
+ except FlamaException as exception:
504
+ logger.error("Error: %s", exception)
505
+ return None
506
+
507
+ def pure_optional_features(self) -> Union[None, List[str]]:
508
+ """
509
+ Returns features with a feature inclusion probability of exactly 0.5, meaning they
510
+ are selected in exactly half of the valid configurations. These are the most
511
+ unconstrained optional features.
512
+ """
513
+ try:
514
+ self._transform_to_bdd()
515
+ return self.discover_metamodel.use_operation(
516
+ self.bdd_model, "BDDPureOptionalFeatures"
517
+ ).get_result()
518
+ except FlamaException as exception:
519
+ logger.error("Error: %s", exception)
520
+ return None
521
+
522
+ def feature_inclusion_probability(self) -> Union[None, Dict[str, float]]:
523
+ """
524
+ Returns a mapping from each feature name to its inclusion probability: the fraction
525
+ of valid configurations in which that feature is selected. Core features have
526
+ probability 1.0 and dead features have probability 0.0.
527
+ """
528
+ try:
529
+ self._transform_to_bdd()
530
+ return self.discover_metamodel.use_operation(
531
+ self.bdd_model, "BDDFeatureInclusionProbability"
532
+ ).get_result()
533
+ except FlamaException as exception:
534
+ logger.error("Error: %s", exception)
535
+ return None
536
+
537
+ def configurations_with_n_features(self, n: int) -> Union[None, List[Configuration]]:
538
+ """
539
+ Returns all valid configurations that have exactly n features selected.
540
+ """
541
+ try:
542
+ self._transform_to_bdd()
543
+ operation = self.discover_metamodel.get_operation(
544
+ self.bdd_model, "BDDConfigurationsWithNFeatures"
545
+ )
546
+ operation.set_n_features(n)
547
+ operation.execute(self.bdd_model)
548
+ return list(operation.get_result())
549
+ except FlamaException as exception:
550
+ logger.error("Error: %s", exception)
551
+ return None
552
+
553
+ def sampling(
554
+ self, size: int, with_replacement: bool = False
555
+ ) -> Union[None, List[Configuration]]:
556
+ """
557
+ Returns a random sample of valid configurations of the given size. When
558
+ with_replacement is True, the same configuration may appear more than once.
559
+ """
560
+ try:
561
+ self._transform_to_bdd()
562
+ operation = self.discover_metamodel.get_operation(self.bdd_model, "BDDSampling")
563
+ operation.set_sample_size(size)
564
+ operation.set_with_replacement(with_replacement)
565
+ operation.execute(self.bdd_model)
566
+ return operation.get_result()
567
+ except FlamaException as exception:
568
+ logger.error("Error: %s", exception)
569
+ return None
570
+
571
+ # Z3-based operations
572
+
573
+ def all_feature_bounds(self) -> Union[None, Dict[str, Dict[str, Any]]]:
574
+ """
575
+ Returns the value bounds for all typed (Integer, Real, String) attribute features in
576
+ the model. Each entry maps a feature name to a dict with 'min', 'max', and 'bounded'
577
+ keys. Requires the z3 metamodel plugin.
578
+ """
579
+ try:
580
+ self._transform_to_z3()
581
+ return self.discover_metamodel.use_operation(
582
+ self.z3_model, "Z3AllFeatureBounds"
583
+ ).get_result()
584
+ except FlamaException as exception:
585
+ logger.error("Error: %s", exception)
586
+ return None
587
+
588
+ def feature_bounds(self, variable_name: str) -> Union[None, Dict[str, Any]]:
589
+ """
590
+ Returns the value bounds for a specific typed attribute feature. The result dict
591
+ contains 'min', 'max', and 'bounded' keys. Requires the z3 metamodel plugin.
592
+ """
593
+ try:
594
+ self._transform_to_z3()
595
+ operation = self.discover_metamodel.get_operation(self.z3_model, "Z3FeatureBounds")
596
+ operation.set_variable_name(variable_name)
597
+ operation.execute(self.z3_model)
598
+ return operation.get_result()
599
+ except FlamaException as exception:
600
+ logger.error("Error: %s", exception)
601
+ return None
602
+
603
+ # Diagnosis-based operations
604
+
605
+ def diagnosis(
606
+ self,
607
+ configuration_path: str,
608
+ test_case_path: str,
609
+ max_diagnoses: Optional[int] = None,
610
+ ) -> Union[None, List[str]]:
611
+ """
612
+ Returns a list of diagnoses explaining why a given configuration does not satisfy
613
+ the test case constraints. Each diagnosis is a minimal set of constraints whose
614
+ removal would resolve the inconsistency. Requires the pysat_diagnosis plugin.
615
+ """
616
+ try:
617
+ self._transform_to_diagnosis()
618
+ configuration = self.discover_metamodel.use_transformation_t2m(
619
+ configuration_path, "configuration"
620
+ )
621
+ test_case = self.discover_metamodel.use_transformation_t2m(
622
+ test_case_path, "configuration"
623
+ )
624
+ operation = self.discover_metamodel.get_operation(
625
+ self.diagnosis_model, "PySATDiagnosis"
626
+ )
627
+ operation.set_configuration(configuration)
628
+ operation.set_test_case(test_case)
629
+ if max_diagnoses is not None:
630
+ operation.set_max_diagnoses(max_diagnoses)
631
+ operation.execute(self.diagnosis_model)
632
+ return operation.get_result()
633
+ except FlamaException as exception:
634
+ logger.error("Error: %s", exception)
635
+ return None
636
+
637
+ def conflict(
638
+ self,
639
+ configuration_path: str,
640
+ test_case_path: str,
641
+ max_conflicts: Optional[int] = None,
642
+ ) -> Union[None, List[str]]:
643
+ """
644
+ Returns a list of conflict sets: minimal subsets of the model constraints that are
645
+ inconsistent with the given configuration and test case. Requires the pysat_diagnosis
646
+ plugin.
647
+ """
648
+ try:
649
+ self._transform_to_diagnosis()
650
+ configuration = self.discover_metamodel.use_transformation_t2m(
651
+ configuration_path, "configuration"
652
+ )
653
+ test_case = self.discover_metamodel.use_transformation_t2m(
654
+ test_case_path, "configuration"
655
+ )
656
+ operation = self.discover_metamodel.get_operation(
657
+ self.diagnosis_model, "PySATConflict"
658
+ )
659
+ operation.set_configuration(configuration)
660
+ operation.set_test_case(test_case)
661
+ if max_conflicts is not None:
662
+ operation.set_max_conflicts(max_conflicts)
663
+ operation.execute(self.diagnosis_model)
664
+ return operation.get_result()
665
+ except FlamaException as exception:
666
+ logger.error("Error: %s", exception)
667
+ return None
@@ -0,0 +1,36 @@
1
+ Metadata-Version: 2.4
2
+ Name: flamapy
3
+ Version: 2.6.0.dev0
4
+ Summary: Flamapy feature model is a distribution of the flama framework containing all plugins required to analyze feature models. It also offers a richer API and a complete command line interface and documentation.
5
+ Author-email: Flamapy <flamapy@us.es>
6
+ License-Expression: GPL-3.0-or-later
7
+ Project-URL: Homepage, https://github.com/flamapy/flamapy-feature-model
8
+ Requires-Python: >=3.9
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: flamapy-fw~=2.6.0.dev0
12
+ Requires-Dist: flamapy-fm~=2.6.0.dev0
13
+ Requires-Dist: flamapy-sat~=2.6.0.dev0
14
+ Requires-Dist: flamapy-bdd~=2.6.0.dev0
15
+ Requires-Dist: flamapy-z3~=2.6.0.dev0
16
+ Provides-Extra: dev
17
+ Requires-Dist: pytest; extra == "dev"
18
+ Requires-Dist: pytest-mock; extra == "dev"
19
+ Requires-Dist: prospector; extra == "dev"
20
+ Requires-Dist: mypy; extra == "dev"
21
+ Requires-Dist: coverage; extra == "dev"
22
+ Dynamic: license-file
23
+
24
+ # flamapy
25
+
26
+ The flamapy feature-model distribution: a meta-package that installs the
27
+ framework and the feature-model analysis plugins, and provides the command-line
28
+ interface and the easy-to-use Python facade (`FLAMAFeatureModel`).
29
+
30
+ **Documentation:** https://docs.flamapy.org
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ pip install flamapy
36
+ ```
@@ -0,0 +1,9 @@
1
+ flamapy/commands/__init__.py,sha256=np1430SLtfuyxNTAFPFNGrB0OunU-KMrOnwWYcwa0VY,6550
2
+ flamapy/interfaces/python/__init__.py,sha256=NVQH1l6O9ElD8YvUVBXJN0Y_ETmu3AbyQBZJJ9qiuoU,86
3
+ flamapy/interfaces/python/flamapy_feature_model.py,sha256=RxUHwn0Wy3QSsrfrDaNuUHjfwCwZWXmdCH8MKxbjW-s,27727
4
+ flamapy-2.6.0.dev0.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
5
+ flamapy-2.6.0.dev0.dist-info/METADATA,sha256=dHRVwXKXLRDI1Wg0rwMKgHIkQdnJs8jCa3pcUeJP2Fw,1264
6
+ flamapy-2.6.0.dev0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
7
+ flamapy-2.6.0.dev0.dist-info/entry_points.txt,sha256=CS_W4K9LW9xOf-7ymWD58KklNHBnhMHm0RXAZ9JLgVo,57
8
+ flamapy-2.6.0.dev0.dist-info/top_level.txt,sha256=2YBI9dg4GVk28AJuyNu6dldi5Riwt5SP0zpNe2lSU5M,8
9
+ flamapy-2.6.0.dev0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (82.0.0)
2
+ Generator: setuptools (82.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,104 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: flamapy
3
- Version: 2.5.0.dev0
4
- Summary: Flamapy feature model is a distribution of the flama framework containing all plugins required to analyze feature models. It also offers a richer API and a complete command line interface and documentation.
5
- Author-email: Flamapy <flamapy@us.es>
6
- License-Expression: GPL-3.0-or-later
7
- Project-URL: Homepage, https://github.com/flamapy/flamapy-feature-model
8
- Requires-Python: >=3.9
9
- Description-Content-Type: text/markdown
10
- License-File: LICENSE
11
- Requires-Dist: flamapy-fw~=2.5.0.dev0
12
- Requires-Dist: flamapy-fm~=2.5.0.dev0
13
- Requires-Dist: flamapy-sat~=2.5.0.dev0
14
- Requires-Dist: flamapy-bdd~=2.5.0.dev0
15
- Provides-Extra: dev
16
- Requires-Dist: pytest; extra == "dev"
17
- Requires-Dist: pytest-mock; extra == "dev"
18
- Requires-Dist: prospector; extra == "dev"
19
- Requires-Dist: mypy; extra == "dev"
20
- Requires-Dist: coverage; extra == "dev"
21
- Dynamic: license-file
22
-
23
- <div align="center">
24
-
25
- <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>
26
- <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>
27
- <a href="">![PyPI](https://img.shields.io/pypi/v/flamapy?label=pypi%20package)
28
- <a href="">![PyPI - Downloads](https://img.shields.io/pypi/dm/flamapy)
29
- </div>
30
-
31
- #
32
-
33
- <div id="top"></div>
34
- <br />
35
- <div align="center">
36
-
37
- <h3 align="center">FLAMAPY</h3>
38
-
39
- <p align="center">
40
- A new and easy way to use FLAMA
41
- <br />
42
- <a href="https://github.com/flamapy/flamapy/issues">Report Bug</a>
43
- ·
44
- <a href="https://github.com/flamapy/flamapy/issues">Request Feature</a>
45
- </p>
46
- </div>
47
- <!-- ABOUT THE PROJECT -->
48
-
49
- # About The Project
50
- 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.
51
-
52
- 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.
53
-
54
- # Using the CMD
55
- ```bash
56
- flamapy --help #This will show the commands available
57
- flamapy satisfiable <path to file> to check if a model is valid
58
- ...
59
- ```
60
- # Using the Python interface
61
- 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:
62
-
63
- ```python
64
- from flamapy.interfaces.python.flama_feature_model import FLAMAFeatureModel
65
-
66
- fm = FLAMAFeatureModel("path/to/feature/model")
67
- print(fm.valid())
68
- ```
69
- # Operations available:
70
- 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.
71
-
72
- * 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.
73
-
74
- * 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.
75
-
76
- * 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.
77
-
78
- * 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.
79
-
80
- * 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.
81
-
82
- * 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.
83
-
84
- * 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.
85
- * 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.
86
-
87
- * 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
88
- features are independent, but in most cases, constraints and dependencies between features need to be taken into account.
89
-
90
- * 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.
91
-
92
- * 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.
93
-
94
- * 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.
95
-
96
- * 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.
97
-
98
- * 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.
99
-
100
- * satisfiable: In the context of feature models, this usually refers to whether the feature model itself satisfies all the
101
- constraints and dependencies. A a valid feature model is one that does encodes at least a single valid product.
102
-
103
- * 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.
104
-
@@ -1,9 +0,0 @@
1
- flamapy/commands/__init__.py,sha256=np1430SLtfuyxNTAFPFNGrB0OunU-KMrOnwWYcwa0VY,6550
2
- flamapy/interfaces/python/__init__.py,sha256=NVQH1l6O9ElD8YvUVBXJN0Y_ETmu3AbyQBZJJ9qiuoU,86
3
- flamapy/interfaces/python/flamapy_feature_model.py,sha256=lNjKO-1VQCw0s7QT0uWcfwVvCM7h2eISSfMbSL7BLhE,15918
4
- flamapy-2.5.0.dev0.dist-info/licenses/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
5
- flamapy-2.5.0.dev0.dist-info/METADATA,sha256=mu_DJDpFhEbEc3Lp0Y23t4nCfTUD4WLduq31-7o-7HI,7733
6
- flamapy-2.5.0.dev0.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
7
- flamapy-2.5.0.dev0.dist-info/entry_points.txt,sha256=CS_W4K9LW9xOf-7ymWD58KklNHBnhMHm0RXAZ9JLgVo,57
8
- flamapy-2.5.0.dev0.dist-info/top_level.txt,sha256=2YBI9dg4GVk28AJuyNu6dldi5Riwt5SP0zpNe2lSU5M,8
9
- flamapy-2.5.0.dev0.dist-info/RECORD,,