mloda 0.4.4__py3-none-any.whl → 0.4.5__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.
@@ -3,18 +3,31 @@ from typing import Any
3
3
 
4
4
 
5
5
  class Domain:
6
- """
7
- Documentation domain:
8
-
9
- default value is default_domain. The purpose of this is to allow for a default domain to be used if no domain is given.
10
- Usecase: Testing, POCS etc. This is a tool to make life easier for the user.
11
-
12
- can be defined by:
13
- feature.domain: either by options or by domain
14
- feature_group.domain: returns the domain name rule for the feature group
15
-
16
- We validate in IdentifyFeatureGroupClass that there is atleast one feature group with the same domain as the feature.
17
- If the feature does not have a domain, and we have not exactly one matching feature group to the feature, we raise an error.
6
+ """Represents a domain for isolating features across business contexts.
7
+
8
+ Domains enable data isolation between different contexts (Sales, Finance, Test, etc.).
9
+ The framework matches feature domains to feature group domains for resolution.
10
+
11
+ Definition:
12
+ - Feature: via `domain` parameter or `options={"domain": "..."}`
13
+ - FeatureGroup: via `get_domain()` classmethod (default: "default_domain")
14
+
15
+ Propagation:
16
+ When a parent feature has a domain, child features inherit it automatically.
17
+ You can override this by setting an explicit domain on each dependent feature.
18
+
19
+ +------------------------------------------+---------------+------------------+
20
+ | Child Definition | Parent Domain | Result |
21
+ +------------------------------------------+---------------+------------------+
22
+ | "child" (string) | "Sales" | Inherits "Sales" |
23
+ | Feature("child") | "Sales" | Inherits "Sales" |
24
+ | Feature("child", domain="Finance") | "Sales" | Keeps "Finance" |
25
+ | Any | None | No domain |
26
+ +------------------------------------------+---------------+------------------+
27
+
28
+ Validation:
29
+ IdentifyFeatureGroupClass ensures at least one feature group matches the feature's domain.
30
+ If a feature has no domain and multiple groups match, an error is raised.
18
31
  """
19
32
 
20
33
  def __init__(self, name: str):
@@ -92,11 +92,8 @@ class FeatureChainParser:
92
92
  """Internal method for matching pattern-based features - used by match_configuration_feature_chain_parser."""
93
93
  _feature_name: FeatureName = FeatureName(feature_name) if isinstance(feature_name, str) else feature_name
94
94
 
95
- try:
96
- has_prefix_configuration, source_feature = cls.parse_feature_name(_feature_name, prefix_patterns, pattern)
97
- if has_prefix_configuration is None or source_feature is None:
98
- return False
99
- except ValueError:
95
+ has_prefix_configuration, source_feature = cls.parse_feature_name(_feature_name, prefix_patterns, pattern)
96
+ if has_prefix_configuration is None or source_feature is None:
100
97
  return False
101
98
  return True
102
99
 
@@ -304,7 +301,6 @@ class FeatureChainParser:
304
301
  return True
305
302
 
306
303
  # configuration-based
307
-
308
304
  if property_mapping is not None:
309
305
  return cls._validate_options_against_property_mapping(options, property_mapping)
310
306
 
@@ -131,13 +131,16 @@ class FeatureChainParserMixin:
131
131
  prefix_patterns = cls._get_prefix_patterns()
132
132
  property_mapping = cls._get_property_mapping()
133
133
 
134
- # Use the unified parser for basic matching
135
- result = FeatureChainParser.match_configuration_feature_chain_parser(
136
- _feature_name,
137
- options,
138
- property_mapping=property_mapping,
139
- prefix_patterns=prefix_patterns,
140
- )
134
+ try:
135
+ # Use the unified parser for basic matching
136
+ result = FeatureChainParser.match_configuration_feature_chain_parser(
137
+ _feature_name,
138
+ options,
139
+ property_mapping=property_mapping,
140
+ prefix_patterns=prefix_patterns,
141
+ )
142
+ except ValueError:
143
+ return False
141
144
 
142
145
  # If basic match succeeded and it's a string-based feature, call validation hook
143
146
  if result:
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
  from typing import Generator, List, Optional, Set, Union
3
3
  from uuid import UUID
4
+ from mloda.core.abstract_plugins.components.domain import Domain
4
5
  from mloda.core.abstract_plugins.components.feature import Feature
5
6
  from mloda.core.abstract_plugins.components.options import Options
6
7
  from mloda_plugins.feature_group.experimental.default_options_key import DefaultOptionKeys
@@ -17,9 +18,11 @@ class Features:
17
18
  features: List[Union[Feature, str]],
18
19
  child_options: Optional[Options] = None,
19
20
  child_uuid: Optional[UUID] = None,
21
+ parent_domain: Optional[str] = None,
20
22
  ) -> None:
21
23
  self.collection: List[Feature] = []
22
24
  self.child_uuid: Optional[UUID] = child_uuid
25
+ self.parent_domain: Optional[str] = parent_domain
23
26
 
24
27
  self.parent_uuids: set[UUID] = set()
25
28
 
@@ -36,7 +39,11 @@ class Features:
36
39
  if child_options.group == {} and child_options.context == {}:
37
40
  child_options = Options({})
38
41
 
39
- feature = Feature(name=feature, options=child_options) if isinstance(feature, str) else feature
42
+ if isinstance(feature, str):
43
+ feature = Feature(name=feature, options=child_options, domain=self.parent_domain)
44
+ else:
45
+ if feature.domain is None and self.parent_domain is not None:
46
+ feature.domain = Domain(self.parent_domain)
40
47
  if child_uuid:
41
48
  self.parent_uuids.add(feature.uuid)
42
49
  self.child_uuid = child_uuid
mloda/core/core/engine.py CHANGED
@@ -116,7 +116,10 @@ class Engine:
116
116
  added = self.add_feature_to_collection(feature_group_class, feature, features.child_uuid)
117
117
 
118
118
  if added:
119
- self._handle_input_features_recursion(feature_group_class, feature.uuid, feature.options, feature.name)
119
+ parent_domain = feature.domain.name if feature.domain else None
120
+ self._handle_input_features_recursion(
121
+ feature_group_class, feature.uuid, feature.options, feature.name, parent_domain=parent_domain
122
+ )
120
123
 
121
124
  if self.global_filter:
122
125
  self._add_filter_feature(feature_group_class, feature_group, feature, features)
@@ -265,7 +268,12 @@ class Engine:
265
268
  self.feature_link_parents[child_uuid].add(wanted_uuid)
266
269
 
267
270
  def _handle_input_features_recursion(
268
- self, feature_group_class: Type[FeatureGroup], uuid: UUID, options: Options, feature_name: FeatureName
271
+ self,
272
+ feature_group_class: Type[FeatureGroup],
273
+ uuid: UUID,
274
+ options: Options,
275
+ feature_name: FeatureName,
276
+ parent_domain: Optional[str] = None,
269
277
  ) -> None:
270
278
  """Handles recursion for input features of a feature group."""
271
279
  feature_group = feature_group_class()
@@ -278,7 +286,9 @@ class Engine:
278
286
  input_features = None
279
287
 
280
288
  if input_features:
281
- features = Features(list(input_features), child_options=options, child_uuid=uuid)
289
+ features = Features(
290
+ list(input_features), child_options=options, child_uuid=uuid, parent_domain=parent_domain
291
+ )
282
292
  if features.child_uuid is None:
283
293
  raise ValueError(f"Features {features} has no parent uuid although it should have one.")
284
294
  self.feature_link_parents[features.child_uuid] = features.parent_uuids
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mloda
3
- Version: 0.4.4
3
+ Version: 0.4.5
4
4
  Summary: mloda.ai: Open Data Access for ML and AI
5
5
  Author-email: Tom Kaltofen <info@mloda.ai>
6
6
  License: Apache-2.0
@@ -10,9 +10,9 @@ mloda/core/abstract_plugins/components/base_feature_group_version.py,sha256=JNnr
10
10
  mloda/core/abstract_plugins/components/base_validator.py,sha256=-8sING9RE9vl5BuZZHtqaMbhF8w1WTS-fjXK5VwMuYY,2363
11
11
  mloda/core/abstract_plugins/components/data_access_collection.py,sha256=PVO6w8UOV6qyyYtlkzXAs-qM7WXsyrHqQP5CYCYu3G8,1551
12
12
  mloda/core/abstract_plugins/components/data_types.py,sha256=uiq26Z7pikUiZIfdi28VbWoxLQUQ1wCH2rp7uI5XrvA,5033
13
- mloda/core/abstract_plugins/components/domain.py,sha256=AzVvWgG3oeHUCXJDtN2heyiUQ1zRK7u5O6az5kWxj_I,1226
13
+ mloda/core/abstract_plugins/components/domain.py,sha256=Jr1bRpaJP3-tYF0ii0tIYv_bpJUqv8SDAk6LljyAAfo,2099
14
14
  mloda/core/abstract_plugins/components/feature.py,sha256=WHK_FIe5EMq1v4ORod3ae8oaDHt4J1uktb9H-0v5m08,10478
15
- mloda/core/abstract_plugins/components/feature_collection.py,sha256=vT4vlZyCRM3G9PtAJHovLoER4ElY08PlTlFzYPcCVyo,4636
15
+ mloda/core/abstract_plugins/components/feature_collection.py,sha256=OfLCspXxAHBBeLri6zIwXs17KWciv1tvXrPq4n3ixqM,4995
16
16
  mloda/core/abstract_plugins/components/feature_name.py,sha256=AgWceOqyHNYGVM5XE1NrGFeZKf9AKtLRoRRaxL7tHzk,673
17
17
  mloda/core/abstract_plugins/components/feature_set.py,sha256=hVJ_t4p30BNOknkMKiyDkYRWbbEd_GtpGf2lW9n3PdM,4226
18
18
  mloda/core/abstract_plugins/components/hashable_dict.py,sha256=xzUIn2wbujo3jwwGayHnSbrrADSiVYU_xUV1nt5Yk8M,426
@@ -21,8 +21,8 @@ mloda/core/abstract_plugins/components/options.py,sha256=z2hzPSl-B-trh1UELdBekAe
21
21
  mloda/core/abstract_plugins/components/parallelization_modes.py,sha256=QeU83qUlg4smUW9Q_cs0XaaBcKDxI7vh8pILUHZd_YM,143
22
22
  mloda/core/abstract_plugins/components/utils.py,sha256=_ofeiOBQLwYU3_p9JBe61Ihps4dpFUcsrqI6XrA92Yo,530
23
23
  mloda/core/abstract_plugins/components/feature_chainer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- mloda/core/abstract_plugins/components/feature_chainer/feature_chain_parser.py,sha256=aGO10OgAfaVs-y4kgSbAtVL2jI7E3EDsfWOkuWlPgDA,14149
25
- mloda/core/abstract_plugins/components/feature_chainer/feature_chain_parser_mixin.py,sha256=yOyWmVd560pV6hL02PyiShNqi6-hMhkME7U80EHWdC8,7444
24
+ mloda/core/abstract_plugins/components/feature_chainer/feature_chain_parser.py,sha256=kjLO0VSGXh53L8HBXWO5bYmaqLmek917AA_qqPLrZBo,14071
25
+ mloda/core/abstract_plugins/components/feature_chainer/feature_chain_parser_mixin.py,sha256=NQfipxPQ6LPN2zXuJAbMj6JaGa6voTBnvb34vp0Y1og,7537
26
26
  mloda/core/abstract_plugins/components/framework_transformer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  mloda/core/abstract_plugins/components/framework_transformer/base_transformer.py,sha256=3eRSOzYZZ4OHRezvUnw4RLTUjirMGtcZCKQYJ1MuuZU,5793
28
28
  mloda/core/abstract_plugins/components/framework_transformer/cfw_transformer.py,sha256=xuK3DSuSdmos1w639ZRQEO6ZwihjQmBG3RSp5jU1gk4,4298
@@ -63,7 +63,7 @@ mloda/core/api/prepare/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
63
63
  mloda/core/api/prepare/setup_compute_framework.py,sha256=In6o7YuBpJFKa6Brrrtsjf1bxhiv43toJr9NBQCAiH4,2658
64
64
  mloda/core/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
65
  mloda/core/core/cfw_manager.py,sha256=DNmbEOIhjKX_G0lva6XqCL0GJIIKy9PfOTXT4g8N9FM,8769
66
- mloda/core/core/engine.py,sha256=yXNbV4LZZaAro1iSEmeFNOKgt5m8P9IIotTjT8jixg4,13690
66
+ mloda/core/core/engine.py,sha256=jQRDyjmDyhGT-LmWyTX_qS87NBz7-xC0ZK0-Ti6OtEo,13962
67
67
  mloda/core/core/step/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
68
  mloda/core/core/step/abstract_step.py,sha256=hIsvJ21hvDXDH1HJSc76WL22FtEvSEN5g7pVpQBEoEU,1304
69
69
  mloda/core/core/step/feature_group_step.py,sha256=3lGaaF0r4FhsSUhdAN7hh3QiNz_0dpW3cRBoKOtaTus,5293
@@ -106,8 +106,8 @@ mloda/steward/__init__.py,sha256=PPXY3o4OM_daV6wD3DJNuPPCEEQg5NeETlG6cAmkzRE,696
106
106
  mloda/steward/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
107
107
  mloda/user/__init__.py,sha256=TG00kApwQzj8FCRIsTy-PomisoULbSTh5CgqlUT6Wvc,1879
108
108
  mloda/user/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
109
- mloda-0.4.4.dist-info/licenses/LICENSE.TXT,sha256=gmhQwSkHxjiShsqQ1FpJ-20YFtaa4vRCE7aCx55-6nk,11366
110
- mloda-0.4.4.dist-info/licenses/NOTICE.md,sha256=Hu10B2sPnGLIHxZ4QhACSLLxukJpeJzjvkzCu48q5fY,520
109
+ mloda-0.4.5.dist-info/licenses/LICENSE.TXT,sha256=gmhQwSkHxjiShsqQ1FpJ-20YFtaa4vRCE7aCx55-6nk,11366
110
+ mloda-0.4.5.dist-info/licenses/NOTICE.md,sha256=Hu10B2sPnGLIHxZ4QhACSLLxukJpeJzjvkzCu48q5fY,520
111
111
  mloda_plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
112
112
  mloda_plugins/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
113
113
  mloda_plugins/compute_framework/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -244,8 +244,8 @@ mloda_plugins/function_extender/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
244
244
  mloda_plugins/function_extender/base_implementations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
245
245
  mloda_plugins/function_extender/base_implementations/otel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
246
246
  mloda_plugins/function_extender/base_implementations/otel/otel_extender.py,sha256=cKFWuVHOzk78Jm4zFfHxdTYcNVAzaM-ORSV0QCkScQM,660
247
- mloda-0.4.4.dist-info/METADATA,sha256=b5c9VSB_4IgwuUtbIFE3KT-EaZQHIn5VCMGRi5zqmQ8,12199
248
- mloda-0.4.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
249
- mloda-0.4.4.dist-info/entry_points.txt,sha256=f7hp7s4laABj9eN5YwEjQAyInF-fa687MXdz-hKYMIA,80
250
- mloda-0.4.4.dist-info/top_level.txt,sha256=zImHD-7ilfeB7QZ6Bd9Htwwx5O-Z84D0T2pUgKrGDdc,20
251
- mloda-0.4.4.dist-info/RECORD,,
247
+ mloda-0.4.5.dist-info/METADATA,sha256=GLEbX7dVW2UqWlG57Mn-_umPJcXvD0v3mVqJTIWNTtw,12199
248
+ mloda-0.4.5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
249
+ mloda-0.4.5.dist-info/entry_points.txt,sha256=f7hp7s4laABj9eN5YwEjQAyInF-fa687MXdz-hKYMIA,80
250
+ mloda-0.4.5.dist-info/top_level.txt,sha256=zImHD-7ilfeB7QZ6Bd9Htwwx5O-Z84D0T2pUgKrGDdc,20
251
+ mloda-0.4.5.dist-info/RECORD,,
File without changes