Skip to content

Commit 354c930

Browse files
committed
added add to environment and updated readme and changes
1 parent c2d37ed commit 354c930

File tree

6 files changed

+170
-14
lines changed

6 files changed

+170
-14
lines changed

CHANGES.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,5 @@
4141
- Updated to support flag sets, large segments and the impressionsDisabled boolean value
4242
3.5.0 (May 6, 2025)
4343
- Updated to support harness mode
44-
3.5.1 (May 8, 2025)
44+
3.5.1 (June 20, 2025)
4545
- Updated to support rule based segments

README.md

Lines changed: 109 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,8 @@ splitDef.submit_change_request(definition, 'UPDATE', 'updating default rule', 'c
284284

285285
### Rule-Based Segments
286286

287+
Rule-based segments allow you to define audience segments using complex rule structures and exclusion logic. Added in version 3.5.1, they offer enhanced functionality for targeting users.
288+
287289
Fetch all Rule-Based Segments:
288290

289291
```python
@@ -313,27 +315,83 @@ env = client.environments.find("Production", ws.id)
313315
segdef = segment.add_to_environment(env.id)
314316
```
315317

318+
#### Rule-Based Segment Structure
319+
320+
Rule-based segment definitions support multiple rule types and matching conditions:
321+
322+
```python
323+
# Examples of different matcher types
324+
matchers = [
325+
# String matching
326+
{
327+
'type': 'IN_LIST_STRING',
328+
'attribute': 'device',
329+
'strings': ['mobile', 'tablet']
330+
},
331+
# Numeric comparisons
332+
{
333+
'type': 'GREATER_THAN_OR_EQUAL_NUMBER',
334+
'attribute': 'age',
335+
'number': 21
336+
},
337+
{
338+
'type': 'LESS_THAN_OR_EQUAL_NUMBER',
339+
'attribute': 'account_age_days',
340+
'number': 30
341+
},
342+
{
343+
'type': 'BETWEEN_NUMBER',
344+
'attribute': 'purchases',
345+
'between': {'from': 5, 'to': 20}
346+
},
347+
# Boolean conditions
348+
{
349+
'type': 'BOOLEAN',
350+
'attribute': 'subscribed',
351+
'bool': True
352+
},
353+
# Date/time matching
354+
{
355+
'type': 'ON_DATE',
356+
'attribute': 'sign_up_date',
357+
'date': 1623456789000 # timestamp in milliseconds
358+
},
359+
# Dependency on another split
360+
{
361+
'type': 'IN_SPLIT',
362+
'attribute': '',
363+
'depends': {'splitName': 'another_split', 'treatment': 'on'}
364+
}
365+
]
366+
367+
# Multiple conditions using combiners
368+
condition = {
369+
'combiner': 'AND', # Can only be 'AND'
370+
'matchers': matchers
371+
}
372+
```
373+
316374
Update Rule-Based Segment definition with rules:
317375

318376
```python
319377
ws = client.workspaces.find("Defaults")
320378
env = client.environments.find("Production", ws.id)
321379
segdef = client.rule_based_segment_definitions.find("advanced_users", env.id, ws.id)
322380

323-
# Define rules that match users with age > 30 and have completed tutorials
381+
# Define rules that match users in a certain list
324382
rules_data = {
325383
'rules': [
326384
{
327385
'condition': {
328386
'combiner': 'AND',
329387
'matchers': [
330388
{
331-
'type': 'GREATER_THAN_OR_EQUAL_TO',
389+
'type': 'GREATER_THAN_OR_EQUAL_NUMBER',
332390
'attribute': 'age',
333391
'number': 30
334392
},
335393
{
336-
'type': 'EQUAL_TO',
394+
'type': 'BOOLEAN',
337395
'attribute': 'completed_tutorials',
338396
'bool': True
339397
}
@@ -347,6 +405,42 @@ rules_data = {
347405
updated_segdef = segdef.update(rules_data)
348406
```
349407

408+
Update Rule-Based Segment definition with excluded keys and excluded segments:
409+
410+
```python
411+
ws = client.workspaces.find("Defaults")
412+
env = client.environments.find("Production", ws.id)
413+
segdef = client.rule_based_segment_definitions.find("advanced_users", env.id, ws.id)
414+
415+
# Define rules and exclusion data
416+
update_data = {
417+
'rules': [
418+
{
419+
'condition': {
420+
'combiner': 'AND',
421+
'matchers': [
422+
{
423+
'type': 'GREATER_THAN_OR_EQUAL_NUMBER',
424+
'attribute': 'age',
425+
'number': 30
426+
}
427+
]
428+
}
429+
}
430+
],
431+
'excludedKeys': ['user1', 'user2', 'user3'],
432+
'excludedSegments': [
433+
{
434+
'name': 'beta_testers',
435+
'type': 'standard_segment'
436+
}
437+
]
438+
}
439+
440+
# Update the segment definition with rules and exclusions
441+
updated_segdef = segdef.update(update_data)
442+
```
443+
350444
Submit a Change request to update a Rule-Based Segment definition:
351445

352446
```python
@@ -375,14 +469,24 @@ rules = [
375469
}
376470
]
377471

378-
# Submit change request
472+
# Define excluded keys and segments for the change request
473+
excluded_keys = ['user1', 'user2']
474+
excluded_segments = [
475+
{
476+
'name': 'test_users',
477+
'type': 'rule_based_segment'
478+
}
479+
]
480+
481+
# Submit change request with all parameters
379482
segdef.submit_change_request(
380483
rules=rules,
484+
excluded_keys=excluded_keys,
485+
excluded_segments=excluded_segments,
381486
operation_type='UPDATE',
382487
title='Lower age threshold to 25',
383488
comment='Including more users in advanced segment',
384489
approvers=['[email protected]'],
385-
rollout_status_id=None,
386490
workspace_id=ws.id
387491
)
388492
```

splitapiclient/microclients/rule_based_segment_definition_microclient.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@ class RuleBasedSegmentDefinitionMicroClient:
3030
}],
3131
'query_string': [],
3232
'response': True,
33+
},
34+
'delete': {
35+
'method': 'DELETE',
36+
'url_template': 'rule-based-segments/{environmentId}/{segmentName}',
37+
'headers': [{
38+
'name': 'Authorization',
39+
'template': 'Bearer {value}',
40+
'required': True,
41+
}],
42+
'query_string': [],
43+
'response': True,
3344
}
3445
}
3546

@@ -121,4 +132,19 @@ def update(self, segment_name, environment_id, workspace_id, data):
121132
)
122133
return RuleBasedSegmentDefinition(as_dict(response), self._http_client)
123134

135+
def delete(self, segment_name, environment_id):
136+
'''
137+
Delete RuleBasedSegmentDefinition object.
138+
139+
:param segment_name: name of the rule-based segment
140+
:param environment_id: id of the environment
124141
142+
:returns: True if successful
143+
:rtype: boolean
144+
'''
145+
self._http_client.make_request(
146+
self._endpoint['delete'],
147+
environmentId = environment_id,
148+
segmentName = segment_name
149+
)
150+
return True

splitapiclient/microclients/rule_based_segment_microclient.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,13 @@ def delete(self, segment_name, workspace_id):
161161
)
162162
return response
163163

164-
def add_to_environment(self, segment_name, environment_id):
164+
def add_to_environment(self, segment_name, environment_id, workspace_id=None):
165165
'''
166166
add a rule-based segment to environment
167167
168-
:param segment: rule-based segment name, environment id
168+
:param segment_name: name of the rule-based segment
169+
:param environment_id: id of the environment
170+
:param workspace_id: id of the workspace (optional)
169171
170172
:returns: newly created rule-based segment definition object
171173
:rtype: RuleBasedSegmentDefinition
@@ -174,9 +176,10 @@ def add_to_environment(self, segment_name, environment_id):
174176
self._endpoint['add_to_environment'],
175177
body="",
176178
segmentName = segment_name,
177-
environmentId = environment_id
179+
environmentId = environment_id,
180+
178181
)
179-
return RuleBasedSegmentDefinition(response, self._http_client)
182+
return RuleBasedSegmentDefinition(response, self._http_client, workspace_id)
180183

181184
def remove_from_environment(self, segment_name, environment_id):
182185
'''

splitapiclient/resources/rule_based_segment.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def add_to_environment(self, environment_id, apiclient=None):
7272
:rtype: RuleBasedSegmentDefinition
7373
'''
7474
imc = require_client('RuleBasedSegment', self._client, apiclient)
75-
return imc.add_to_environment(self._name, environment_id)
75+
return imc.add_to_environment(self._name, environment_id=environment_id, workspace_id=self._workspace_id)
7676

7777
def remove_from_environment(self, environment_id, apiclient=None):
7878
'''

splitapiclient/resources/rule_based_segment_definition.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class RuleBasedSegmentDefinition(BaseResource):
4444
}]
4545
}
4646

47-
def __init__(self, data=None, client=None):
47+
def __init__(self, data=None, client=None, workspace_id=None):
4848
'''
4949
Constructor for RuleBasedSegmentDefinition
5050
'''
@@ -58,6 +58,8 @@ def __init__(self, data=None, client=None):
5858
self._excludedKeys = data.get('excludedKeys', [])
5959
self._excludedSegments = data.get('excludedSegments', [])
6060
self._rules = data.get('rules', [])
61+
self._workspace_id = workspace_id
62+
6163

6264
@property
6365
def name(self):
@@ -91,20 +93,41 @@ def excluded_segments(self):
9193
def rules(self):
9294
return self._rules
9395

94-
def update(self, data, apiclient=None):
96+
def delete(self, apiclient=None):
97+
'''
98+
Delete RuleBasedSegmentDefinition object.
99+
100+
:param apiclient: If this instance wasn't returned by the client,
101+
the ApiClient instance should be passed in order to perform the
102+
http call
103+
104+
:returns: True if successful
105+
:rtype: boolean
106+
'''
107+
imc = require_client('RuleBasedSegmentDefinition', self._client, apiclient)
108+
return imc.delete(self._name, self._environment['id'])
109+
110+
111+
def update(self, data, workspace_id=None, apiclient=None):
95112
'''
96113
Update RuleBasedSegmentDefinition object.
97114
98115
:param data: dictionary of data to update
116+
:param workspace_id: id of the workspace
99117
:param apiclient: If this instance wasn't returned by the client,
100118
the ApiClient instance should be passed in order to perform the
101119
http call
102120
103121
:returns: RuleBasedSegmentDefinition object
104122
:rtype: RuleBasedSegmentDefinition
105123
'''
124+
if not workspace_id:
125+
workspace_id = self._workspace_id
126+
127+
if workspace_id is None:
128+
raise ValueError("workspace_id is required argument")
106129
imc = require_client('RuleBasedSegmentDefinition', self._client, apiclient)
107-
return imc.update(self._name, self._environment['id'], self._client._workspace_id, data)
130+
return imc.update(self._name, self._environment['id'], workspace_id, data)
108131

109132
def submit_change_request(self, rules, excluded_keys, excluded_segments, operation_type, title, comment, approvers, workspace_id, apiclient=None):
110133
'''

0 commit comments

Comments
 (0)