ibm-appconfiguration-python-sdk 0.4.1__tar.gz → 0.4.2__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.
Files changed (59) hide show
  1. {ibm_appconfiguration_python_sdk-0.4.1/ibm_appconfiguration_python_sdk.egg-info → ibm_appconfiguration_python_sdk-0.4.2}/PKG-INFO +1 -1
  2. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/configuration_handler.py +83 -5
  3. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/common/config_constants.py +5 -1
  4. ibm_appconfiguration_python_sdk-0.4.2/ibm_appconfiguration/configurations/internal/utils/rollout_utils.py +101 -0
  5. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/models/feature.py +16 -1
  6. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/models/segment_rules.py +22 -1
  7. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/version.py +1 -1
  8. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2/ibm_appconfiguration_python_sdk.egg-info}/PKG-INFO +1 -1
  9. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration_python_sdk.egg-info/SOURCES.txt +1 -0
  10. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/setup.py +1 -1
  11. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/LICENSE +0 -0
  12. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/README.md +0 -0
  13. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/examples/__init__.py +0 -0
  14. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/examples/sample_app.py +0 -0
  15. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/examples/server_sample.py +0 -0
  16. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/__init__.py +0 -0
  17. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/appconfiguration.py +0 -0
  18. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/__init__.py +0 -0
  19. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/__init__.py +0 -0
  20. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/common/__init__.py +0 -0
  21. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/common/config_messages.py +0 -0
  22. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/utils/__init__.py +0 -0
  23. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/utils/api_manager.py +0 -0
  24. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/utils/compute_percentage.py +0 -0
  25. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/utils/connectivity.py +0 -0
  26. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/utils/file_manager.py +0 -0
  27. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/utils/logger.py +0 -0
  28. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/utils/metering.py +0 -0
  29. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/utils/parser.py +0 -0
  30. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/utils/socket.py +0 -0
  31. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/utils/url_builder.py +0 -0
  32. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/internal/utils/validators.py +0 -0
  33. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/models/__init__.py +0 -0
  34. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/models/configuration_type.py +0 -0
  35. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/models/property.py +0 -0
  36. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/models/rule.py +0 -0
  37. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration/configurations/models/segment.py +0 -0
  38. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration_python_sdk.egg-info/dependency_links.txt +0 -0
  39. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration_python_sdk.egg-info/requires.txt +0 -0
  40. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/ibm_appconfiguration_python_sdk.egg-info/top_level.txt +0 -0
  41. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/integration_tests/__init__.py +0 -0
  42. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/integration_tests/test_integration.py +0 -0
  43. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/setup.cfg +0 -0
  44. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/__init__.py +0 -0
  45. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/configurations/__init__.py +0 -0
  46. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/configurations/models/__init__.py +0 -0
  47. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/configurations/models/test_feature.py +0 -0
  48. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/configurations/models/test_property.py +0 -0
  49. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/configurations/models/test_rule.py +0 -0
  50. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/configurations/models/test_segment.py +0 -0
  51. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/configurations/models/test_segment_rules.py +0 -0
  52. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/configurations/test_configuration_handler.py +0 -0
  53. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/configurations/utils/__init__.py +0 -0
  54. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/configurations/utils/test_api_manager.py +0 -0
  55. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/configurations/utils/test_file_manager.py +0 -0
  56. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/configurations/utils/test_metering.py +0 -0
  57. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/configurations/utils/test_socket.py +0 -0
  58. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/configurations/utils/test_url_builder.py +0 -0
  59. {ibm_appconfiguration_python_sdk-0.4.1 → ibm_appconfiguration_python_sdk-0.4.2}/unit_tests/test_appconfiguration.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ibm-appconfiguration-python-sdk
3
- Version: 0.4.1
3
+ Version: 0.4.2
4
4
  Summary: IBM Cloud App Configuration Python SDK
5
5
  Home-page: https://github.com/IBM/appconfiguration-python-sdk
6
6
  Author: IBM
@@ -33,6 +33,7 @@ from .internal.utils.metering import Metering
33
33
  from .internal.utils.socket import Socket
34
34
  from .internal.utils.url_builder import URLBuilder
35
35
  from .internal.utils.api_manager import APIManager
36
+ from .internal.utils.rollout_utils import parse_rollout_configuration_phases, get_current_rollout_percentage
36
37
 
37
38
 
38
39
  class ConfigurationHandler:
@@ -61,6 +62,7 @@ class ConfigurationHandler:
61
62
  self.__feature_map = dict()
62
63
  self.__property_map = dict()
63
64
  self.__segment_map = dict()
65
+ self.__rollout_config_map = dict()
64
66
  self.__live_config_update_enabled = True
65
67
  ConfigurationHandler.__instance = self
66
68
  self.__retry_interval = 120
@@ -97,6 +99,7 @@ class ConfigurationHandler:
97
99
  self.__feature_map = dict()
98
100
  self.__property_map = dict()
99
101
  self.__segment_map = dict()
102
+ self.__rollout_config_map = dict()
100
103
 
101
104
  def set_context(self, collection_id: str, environment_id: str, options: dict):
102
105
  """Set the context for the configuration
@@ -249,11 +252,33 @@ class ConfigurationHandler:
249
252
  if len(data) != 0:
250
253
  if 'features' in data:
251
254
  self.__feature_map = dict()
255
+ self.__rollout_config_map = dict()
252
256
  try:
253
257
  all_feature_list: List = data.get('features')
254
258
  for i, feature in enumerate(all_feature_list):
255
259
  feature_obj = Feature(feature)
256
260
  self.__feature_map[feature_obj.get_feature_id()] = feature_obj
261
+
262
+ # Parse feature-level progressive rollout
263
+ if feature_obj.get_rollout_configuration() is not None:
264
+ rollout_config = feature_obj.get_rollout_configuration()
265
+ if rollout_config:
266
+ rollout_map = parse_rollout_configuration_phases(rollout_config)
267
+ if rollout_map:
268
+ self.__rollout_config_map[feature_obj.get_feature_id()] = rollout_map
269
+
270
+ # Parse segment-level progressive rollout
271
+ segment_rules = feature_obj.get_segment_rules()
272
+ if segment_rules and isinstance(segment_rules, list):
273
+ for segment_rule in segment_rules:
274
+ segment_rule_obj = SegmentRules(segment_rule)
275
+ if segment_rule_obj.get_rollout_configuration() is not None:
276
+ rollout_config = segment_rule_obj.get_rollout_configuration()
277
+ if rollout_config and segment_rule_obj.get_rule_id():
278
+ rollout_map = parse_rollout_configuration_phases(rollout_config)
279
+ if rollout_map:
280
+ key = feature_obj.get_feature_id() + config_constants.DELIMITER + segment_rule_obj.get_rule_id()
281
+ self.__rollout_config_map[key] = rollout_map
257
282
  except Exception as err:
258
283
  Logger.debug(err)
259
284
 
@@ -359,8 +384,21 @@ class ConfigurationHandler:
359
384
  if feature.get_feature_data_format() == "YAML" and type(result_dict['value']) == str:
360
385
  return Validators.validate_yaml_string(result_dict['value']), result_dict['is_enabled']
361
386
  return result_dict['value'], result_dict['is_enabled']
362
- if feature.get_rollout_percentage() == 100 or (get_normalized_value(
363
- entity_id + ":" + feature.get_feature_id()) < feature.get_rollout_percentage()):
387
+
388
+ # Check feature-level rollout
389
+ rollout_percentage = None
390
+ if feature.get_rollout_configuration() is not None:
391
+ rollout_map = self.__rollout_config_map.get(feature.get_feature_id())
392
+ if rollout_map:
393
+ entity_id += feature.get_rollout_configuration().get('start_at')
394
+ rollout_percentage = get_current_rollout_percentage(rollout_map)
395
+ else:
396
+ rollout_percentage = 0
397
+ else:
398
+ rollout_percentage = feature.get_rollout_percentage() if feature.get_rollout_percentage() is not None else 100
399
+
400
+ if rollout_percentage == 100 or (get_normalized_value(
401
+ entity_id + ":" + feature.get_feature_id()) < rollout_percentage):
364
402
  return feature.get_enabled_value(), True
365
403
  return feature.get_disabled_value(), False
366
404
  return feature.get_disabled_value(), False
@@ -391,7 +429,35 @@ class ConfigurationHandler:
391
429
  result_dict['evaluated_segment_id'] = segment_key
392
430
  if feature is not None:
393
431
  # evaluate_rules was called for feature flag
394
- segment_rollout_percentage = feature.get_rollout_percentage() if segment_rule.get_rollout_percentage() == config_constants.DEFAULT_ROLLOUT_PERCENTAGE else segment_rule.get_rollout_percentage()
432
+ segment_rollout_percentage = None
433
+
434
+ # Check if segment rule has progressive rollout
435
+ if segment_rule.get_rollout_configuration() is not None or segment_rule.get_rollout_type() == config_constants.PROGRESSIVE:
436
+ # Determine which rollout map to use
437
+ if segment_rule.get_rollout_percentage() == config_constants.DEFAULT_ROLLOUT_PERCENTAGE:
438
+ # Use feature-level rollout
439
+ rollout_map = self.__rollout_config_map.get(feature.get_feature_id())
440
+ else:
441
+ # Use segment-level rollout
442
+ rule_id = segment_rule.get_rule_id()
443
+ if rule_id:
444
+ key = feature.get_feature_id() + config_constants.DELIMITER + rule_id
445
+ rollout_map = self.__rollout_config_map.get(key)
446
+ else:
447
+ rollout_map = None
448
+
449
+ if rollout_map:
450
+ entity_id += segment_rule.get_rollout_configuration().get('start_at')
451
+ segment_rollout_percentage = get_current_rollout_percentage(rollout_map)
452
+ else:
453
+ segment_rollout_percentage = 0
454
+ else:
455
+ # Use manual rollout percentage
456
+ if segment_rule.get_rollout_percentage() == config_constants.DEFAULT_ROLLOUT_PERCENTAGE:
457
+ segment_rollout_percentage = feature.get_rollout_percentage() if feature.get_rollout_percentage() is not None else 100
458
+ else:
459
+ segment_rollout_percentage = segment_rule.get_rollout_percentage() if segment_rule.get_rollout_percentage() is not None else 100
460
+
395
461
  if segment_rollout_percentage == 100 or (get_normalized_value(
396
462
  entity_id + ":" + feature.get_feature_id())) < segment_rollout_percentage:
397
463
  if segment_rule.get_value() == config_constants.DEFAULT_FEATURE_VALUE:
@@ -413,8 +479,20 @@ class ConfigurationHandler:
413
479
  Logger.debug(err)
414
480
 
415
481
  if feature is not None:
416
- if feature.get_rollout_percentage() == 100 or get_normalized_value(
417
- entity_id + ":" + feature.get_feature_id()) < feature.get_rollout_percentage():
482
+ # Check feature-level rollout
483
+ rollout_percentage = None
484
+ if feature.get_rollout_configuration() is not None:
485
+ rollout_map = self.__rollout_config_map.get(feature.get_feature_id())
486
+ if rollout_map:
487
+ entity_id += feature.get_rollout_configuration().get('start_at')
488
+ rollout_percentage = get_current_rollout_percentage(rollout_map)
489
+ else:
490
+ rollout_percentage = 0
491
+ else:
492
+ rollout_percentage = feature.get_rollout_percentage() if feature.get_rollout_percentage() is not None else 100
493
+
494
+ if rollout_percentage == 100 or get_normalized_value(
495
+ entity_id + ":" + feature.get_feature_id()) < rollout_percentage:
418
496
  result_dict['value'] = feature.get_enabled_value()
419
497
  result_dict['is_enabled'] = True
420
498
  else:
@@ -18,7 +18,7 @@ This file defines the constants used by the SDK.
18
18
 
19
19
  DEFAULT_SEGMENT_ID = '$$null$$'
20
20
  DEFAULT_ENTITY_ID = '$$null$$'
21
- DEFAULT_USAGE_LIMIT = 10
21
+ DEFAULT_USAGE_LIMIT = 30
22
22
  SDK_NAME = "appconfiguration-python-sdk"
23
23
  MAX_NUMBER_OF_RETRIES = 3
24
24
  DEFAULT_ROLLOUT_PERCENTAGE = '$default'
@@ -26,3 +26,7 @@ DEFAULT_FEATURE_VALUE = '$default'
26
26
  DEFAULT_PROPERTY_VALUE = '$default'
27
27
  WEBSOCKET_RECONNECT_DELAY = 15 # Constant delay between reconnection attempts for server errors
28
28
  CUSTOM_SOCKET_CLOSE_REASON_CODE = 4001
29
+
30
+ MANUAL = 'MANUAL'
31
+ PROGRESSIVE = 'PROGRESSIVE'
32
+ DELIMITER = '\u001F'
@@ -0,0 +1,101 @@
1
+ # Copyright 2021 IBM All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ Utility module for handling progressive rollout configurations.
17
+ """
18
+
19
+ from datetime import datetime
20
+ from sortedcontainers import SortedDict
21
+ from .logger import Logger
22
+
23
+
24
+ def parse_rollout_configuration_phases(configuration: dict) -> SortedDict:
25
+ """
26
+ Parse progressive rollout phases into a SortedDict for efficient timestamp-to-percentage lookups.
27
+
28
+ Args:
29
+ configuration: Rollout configuration dict with 'start_at' and 'phases' keys
30
+
31
+ Returns:
32
+ SortedDict with timestamps (ms) as keys and percentages as values, or None if parsing fails
33
+ """
34
+ if not configuration or 'start_at' not in configuration or 'phases' not in configuration:
35
+ return None
36
+
37
+ if not isinstance(configuration['phases'], list) or len(configuration['phases']) == 0:
38
+ return None
39
+
40
+ try:
41
+ # Parse start timestamp
42
+ start_time = datetime.fromisoformat(configuration['start_at'].replace('Z', '+00:00'))
43
+ transition_time = int(start_time.timestamp() * 1000) # Convert to milliseconds
44
+
45
+ # Create SortedDict for efficient lookups
46
+ result = SortedDict()
47
+ result[0] = 0
48
+
49
+ # Duration multipliers in milliseconds
50
+ multipliers = {
51
+ 'days': 86400000, # days
52
+ 'hours': 3600000, # hours
53
+ 'minutes': 60000, # minutes
54
+ }
55
+
56
+ for phase in configuration['phases']:
57
+ if not isinstance(phase, dict) or 'percentage' not in phase:
58
+ continue
59
+
60
+ # Add phase entry
61
+ result[transition_time] = phase['percentage']
62
+
63
+ # Calculate next transition time if duration is specified
64
+ duration = phase.get('duration')
65
+ if duration:
66
+ transition_time += multipliers.get(phase.get('duration_type')) * duration
67
+
68
+ return result
69
+
70
+ except (ValueError, AttributeError) as e:
71
+ Logger.error(f"Invalid start_at timestamp: {configuration.get('start_at')}, error: {str(e)}")
72
+ return None
73
+ except Exception as e:
74
+ Logger.error(f"Error parsing rollout configuration: {str(e)}")
75
+ return None
76
+
77
+
78
+ def get_current_rollout_percentage(rollout_map: SortedDict) -> int:
79
+ """
80
+ Returns the current rollout percentage based on current time.
81
+
82
+ Args:
83
+ rollout_map: SortedDict containing timestamp-to-percentage mappings
84
+
85
+ Returns:
86
+ The current rollout percentage, or 0 if rollout_map is None or empty
87
+ """
88
+ if not rollout_map or len(rollout_map) == 0:
89
+ return 0
90
+
91
+ current_time = int(datetime.now().timestamp() * 1000) # Current time in milliseconds
92
+
93
+ # Find the entry with the largest timestamp that is <= current_time
94
+ # SortedDict.bisect_right returns the index where current_time would be inserted
95
+ # We want the item just before that position
96
+ idx = rollout_map.bisect_right(current_time)
97
+ if idx > 0:
98
+ key = rollout_map.keys()[idx - 1]
99
+ return rollout_map[key]
100
+
101
+ return 0
@@ -20,6 +20,7 @@ from typing import Any
20
20
  from ..internal.utils.logger import Logger
21
21
  from ..internal.utils.validators import Validators
22
22
  from .configuration_type import ConfigurationType
23
+ from ..internal.common import config_constants
23
24
 
24
25
 
25
26
  class Feature:
@@ -39,7 +40,13 @@ class Feature:
39
40
  self.__format = feature_list.get('format', None)
40
41
  self.__disabled_value = feature_list.get('disabled_value', object)
41
42
  self.__enabled_value = feature_list.get('enabled_value', object)
42
- self.__rollout_percentage = feature_list.get('rollout_percentage', 100)
43
+ self.__rollout_type = feature_list.get('rollout_type', config_constants.MANUAL)
44
+ if feature_list.get('rollout_configuration', None) is not None:
45
+ self.__rollout_configuration = feature_list.get('rollout_configuration')
46
+ self.__rollout_percentage = None
47
+ else:
48
+ self.__rollout_percentage = feature_list.get('rollout_percentage', 100)
49
+ self.__rollout_configuration = None
43
50
 
44
51
  def get_feature_name(self) -> str:
45
52
  """Get the Feature name"""
@@ -74,6 +81,14 @@ class Feature:
74
81
  def get_rollout_percentage(self) -> int:
75
82
  """Get the Feature flag's rollout percentage"""
76
83
  return self.__rollout_percentage
84
+
85
+ def get_rollout_type(self) -> str:
86
+ """Get the Feature flag's rollout type"""
87
+ return self.__rollout_type
88
+
89
+ def get_rollout_configuration(self) -> Any:
90
+ """Get the Feature flag's rollout configuration"""
91
+ return self.__rollout_configuration
77
92
 
78
93
  def is_enabled(self) -> bool:
79
94
  """
@@ -15,6 +15,8 @@
15
15
  This module defines the model of a segment rule defined in App Configuration service.
16
16
  """
17
17
 
18
+ from ..internal.common import config_constants
19
+
18
20
 
19
21
  class SegmentRules:
20
22
  """
@@ -26,7 +28,14 @@ class SegmentRules:
26
28
  self.__order = segment_rules.get("order", 1)
27
29
  self.__value = segment_rules.get("value", object)
28
30
  self.__rules = segment_rules.get("rules", list())
29
- self.__rollout_percentage = segment_rules.get("rollout_percentage", 100)
31
+ self.__rule_id = segment_rules.get("rule_id", None)
32
+ self.__rollout_type = segment_rules.get("rollout_type", config_constants.MANUAL)
33
+ if segment_rules.get("rollout_configuration", None) is not None:
34
+ self.__rollout_configuration = segment_rules.get("rollout_configuration")
35
+ self.__rollout_percentage = None
36
+ else:
37
+ self.__rollout_percentage = segment_rules.get("rollout_percentage", 100)
38
+ self.__rollout_configuration = None
30
39
 
31
40
  def get_order(self) -> int:
32
41
  """Get the SegmentRule order"""
@@ -43,3 +52,15 @@ class SegmentRules:
43
52
  def get_rollout_percentage(self) -> int:
44
53
  """Get the rollout percentage for SegmentRule"""
45
54
  return self.__rollout_percentage
55
+
56
+ def get_rule_id(self) -> str:
57
+ """Get the rule ID for SegmentRule"""
58
+ return self.__rule_id
59
+
60
+ def get_rollout_type(self) -> str:
61
+ """Get the rollout type for SegmentRule"""
62
+ return self.__rollout_type
63
+
64
+ def get_rollout_configuration(self) -> dict:
65
+ """Get the rollout configuration for SegmentRule"""
66
+ return self.__rollout_configuration
@@ -15,4 +15,4 @@
15
15
  """
16
16
  Version of ibm-appconfiguration-python-sdk
17
17
  """
18
- __version__ = '0.4.1'
18
+ __version__ = '0.4.2'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ibm-appconfiguration-python-sdk
3
- Version: 0.4.1
3
+ Version: 0.4.2
4
4
  Summary: IBM Cloud App Configuration Python SDK
5
5
  Home-page: https://github.com/IBM/appconfiguration-python-sdk
6
6
  Author: IBM
@@ -21,6 +21,7 @@ ibm_appconfiguration/configurations/internal/utils/file_manager.py
21
21
  ibm_appconfiguration/configurations/internal/utils/logger.py
22
22
  ibm_appconfiguration/configurations/internal/utils/metering.py
23
23
  ibm_appconfiguration/configurations/internal/utils/parser.py
24
+ ibm_appconfiguration/configurations/internal/utils/rollout_utils.py
24
25
  ibm_appconfiguration/configurations/internal/utils/socket.py
25
26
  ibm_appconfiguration/configurations/internal/utils/url_builder.py
26
27
  ibm_appconfiguration/configurations/internal/utils/validators.py
@@ -12,7 +12,7 @@
12
12
  from setuptools import setup, find_packages
13
13
 
14
14
  NAME = "ibm-appconfiguration-python-sdk"
15
- VERSION = "0.4.1"
15
+ VERSION = "0.4.2"
16
16
  # To install the library, run the following
17
17
  #
18
18
  # python setup.py install