Skip to content

Commit 71fb924

Browse files
authored
Merge pull request #24 from splitio/351-rule-based-segments
351 - added support for rule based segments
2 parents 8162397 + a09aed1 commit 71fb924

25 files changed

+2203
-10
lines changed

CHANGES.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,6 @@
4040
3.2.0 (Feb 2, 2025)
4141
- Updated to support flag sets, large segments and the impressionsDisabled boolean value
4242
3.5.0 (May 6, 2025)
43-
- Updated to support harness mode
43+
- Updated to support harness mode
44+
3.5.1 (June 20, 2025)
45+
- Updated to support rule based segments

README.md

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,214 @@ definition= {"treatments":[ {"name":"on"},{"name":"off"}],
282282
splitDef.submit_change_request(definition, 'UPDATE', 'updating default rule', 'comment', ['[email protected]'], '')
283283
```
284284

285+
### Rule-Based Segments
286+
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+
289+
Fetch all Rule-Based Segments:
290+
291+
```python
292+
ws = client.workspaces.find("Defaults")
293+
for segment in client.rule_based_segments.list(ws.id):
294+
print("\nRule-Based Segment: " + segment.name + ", " + segment.description)
295+
```
296+
297+
Add new Rule-Based Segment:
298+
299+
```python
300+
segment_data = {
301+
'name': 'advanced_users',
302+
'description': 'Users who match advanced criteria'
303+
}
304+
rule_segment = ws.add_rule_based_segment(segment_data, "user")
305+
print(rule_segment.name)
306+
```
307+
308+
Add Rule-Based Segment to environment:
309+
310+
```python
311+
ws = client.workspaces.find("Defaults")
312+
segment = client.rule_based_segments.find("advanced_users", ws.id)
313+
env = client.environments.find("Production", ws.id)
314+
segdef = segment.add_to_environment(env.id)
315+
```
316+
317+
#### Rule-Based Segment Structure
318+
319+
Rule-based segment definitions support multiple rule types and matching conditions:
320+
321+
```python
322+
# Examples of different matcher types
323+
matchers = [
324+
# String matching
325+
{
326+
'type': 'IN_LIST_STRING',
327+
'attribute': 'device',
328+
'strings': ['mobile', 'tablet']
329+
},
330+
# Numeric comparisons
331+
{
332+
'type': 'GREATER_THAN_OR_EQUAL_NUMBER',
333+
'attribute': 'age',
334+
'number': 21
335+
},
336+
{
337+
'type': 'LESS_THAN_OR_EQUAL_NUMBER',
338+
'attribute': 'account_age_days',
339+
'number': 30
340+
},
341+
{
342+
'type': 'BETWEEN_NUMBER',
343+
'attribute': 'purchases',
344+
'between': {'from': 5, 'to': 20}
345+
},
346+
# Boolean conditions
347+
{
348+
'type': 'BOOLEAN',
349+
'attribute': 'subscribed',
350+
'bool': True
351+
},
352+
# Date/time matching
353+
{
354+
'type': 'ON_DATE',
355+
'attribute': 'sign_up_date',
356+
'date': 1623456789000 # timestamp in milliseconds
357+
},
358+
# Dependency on another split
359+
{
360+
'type': 'IN_SPLIT',
361+
'attribute': '',
362+
'depends': {'splitName': 'another_split', 'treatment': 'on'}
363+
}
364+
]
365+
366+
# Multiple conditions using combiners
367+
condition = {
368+
'combiner': 'AND', # Can only be 'AND'
369+
'matchers': matchers
370+
}
371+
```
372+
373+
Update Rule-Based Segment definition with rules:
374+
375+
```python
376+
ws = client.workspaces.find("Defaults")
377+
env = client.environments.find("Production", ws.id)
378+
segdef = client.rule_based_segment_definitions.find("advanced_users", env.id, ws.id)
379+
380+
# Define rules that match users in a certain list
381+
rules_data = {
382+
'rules': [
383+
{
384+
'condition': {
385+
'combiner': 'AND',
386+
'matchers': [
387+
{
388+
'type': 'GREATER_THAN_OR_EQUAL_NUMBER',
389+
'attribute': 'age',
390+
'number': 30
391+
},
392+
{
393+
'type': 'BOOLEAN',
394+
'attribute': 'completed_tutorials',
395+
'bool': True
396+
}
397+
]
398+
}
399+
}
400+
]
401+
}
402+
403+
# Update the segment definition with the rules
404+
updated_segdef = segdef.update(rules_data)
405+
```
406+
407+
Update Rule-Based Segment definition with excluded keys and excluded segments:
408+
409+
```python
410+
ws = client.workspaces.find("Defaults")
411+
env = client.environments.find("Production", ws.id)
412+
segdef = client.rule_based_segment_definitions.find("advanced_users", env.id, ws.id)
413+
414+
# Define rules and exclusion data
415+
update_data = {
416+
'rules': [
417+
{
418+
'condition': {
419+
'combiner': 'AND',
420+
'matchers': [
421+
{
422+
'type': 'GREATER_THAN_OR_EQUAL_NUMBER',
423+
'attribute': 'age',
424+
'number': 30
425+
}
426+
]
427+
}
428+
}
429+
],
430+
'excludedKeys': ['user1', 'user2', 'user3'],
431+
'excludedSegments': [
432+
{
433+
'name': 'beta_testers',
434+
'type': 'standard_segment'
435+
}
436+
]
437+
}
438+
439+
# Update the segment definition with rules and exclusions
440+
updated_segdef = segdef.update(update_data)
441+
```
442+
443+
Submit a Change request to update a Rule-Based Segment definition:
444+
445+
```python
446+
ws = client.workspaces.find("Defaults")
447+
env = client.environments.find("Production", ws.id)
448+
segdef = client.rule_based_segment_definitions.find("advanced_users", env.id, ws.id)
449+
450+
# New rules for the change request
451+
rules = [
452+
{
453+
'condition': {
454+
'combiner': 'AND',
455+
'matchers': [
456+
{
457+
'type': 'GREATER_THAN_OR_EQUAL_NUMBER',
458+
'attribute': 'age',
459+
'number': 25
460+
},
461+
{
462+
'type': 'BOOLEAN',
463+
'attribute': 'completed_tutorials',
464+
'bool': True
465+
}
466+
]
467+
}
468+
}
469+
]
470+
471+
# Define excluded keys and segments for the change request
472+
excluded_keys = ['user1', 'user2']
473+
excluded_segments = [
474+
{
475+
'name': 'test_users',
476+
'type': 'rule_based_segment'
477+
}
478+
]
479+
480+
# Submit change request with all parameters
481+
segdef.submit_change_request(
482+
rules=rules,
483+
excluded_keys=excluded_keys,
484+
excluded_segments=excluded_segments,
485+
operation_type='UPDATE',
486+
title='Lower age threshold to 25',
487+
comment='Including more users in advanced segment',
488+
approvers=['[email protected]'],
489+
workspace_id=ws.id
490+
)
491+
```
492+
285493
List all change requests:
286494

287495
```python

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "splitapiclient"
7-
version = "3.5.0"
7+
version = "3.5.1"
88
description = "This Python Library provide full support for Split REST Admin API, allow creating, deleting and editing Environments, Splits, Split Definitions, Segments, Segment Keys, Users, Groups, API Keys, Change Requests, Attributes and Identities"
99
classifiers = [
1010
"Programming Language :: Python :: 3",

splitapiclient/main/apiclient.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ def segments(self):
3535
@abc.abstractproperty
3636
def segment_definitions(self):
3737
pass
38+
39+
@abc.abstractproperty
40+
def rule_based_segments(self):
41+
pass
42+
43+
@abc.abstractproperty
44+
def rule_based_segment_definitions(self):
45+
pass
3846

3947
@abc.abstractproperty
4048
def workspaces(self):

splitapiclient/main/sync_apiclient.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
from splitapiclient.microclients import SplitDefinitionMicroClient
1010
from splitapiclient.microclients import SegmentMicroClient
1111
from splitapiclient.microclients import SegmentDefinitionMicroClient
12+
from splitapiclient.microclients import RuleBasedSegmentMicroClient
13+
from splitapiclient.microclients import RuleBasedSegmentDefinitionMicroClient
1214
from splitapiclient.microclients import WorkspaceMicroClient
1315
from splitapiclient.microclients import IdentityMicroClient
1416
from splitapiclient.microclients import AttributeMicroClient
@@ -67,6 +69,8 @@ def __init__(self, config):
6769
self._split_definition_client = SplitDefinitionMicroClient(http_client)
6870
self._segment_client = SegmentMicroClient(http_client)
6971
self._segment_definition_client = SegmentDefinitionMicroClient(http_client)
72+
self._rule_based_segment_client = RuleBasedSegmentMicroClient(http_client)
73+
self._rule_based_segment_definition_client = RuleBasedSegmentDefinitionMicroClient(http_client)
7074
self._large_segment_client = LargeSegmentMicroClient(http_client)
7175
self._large_segment_definition_client = LargeSegmentDefinitionMicroClient(http_client)
7276
self._workspace_client = WorkspaceMicroClient(http_client)
@@ -103,6 +107,14 @@ def segments(self):
103107
@property
104108
def segment_definitions(self):
105109
return self._segment_definition_client
110+
111+
@property
112+
def rule_based_segments(self):
113+
return self._rule_based_segment_client
114+
115+
@property
116+
def rule_based_segment_definitions(self):
117+
return self._rule_based_segment_definition_client
106118

107119
@property
108120
def large_segments(self):

splitapiclient/microclients/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@
1414
from splitapiclient.microclients.restriction_microclient import RestrictionMicroClient
1515
from splitapiclient.microclients.flag_set_microclient import FlagSetMicroClient
1616
from splitapiclient.microclients.large_segment_microclient import LargeSegmentMicroClient
17-
from splitapiclient.microclients.large_segment_definition_microclient import LargeSegmentDefinitionMicroClient
17+
from splitapiclient.microclients.large_segment_definition_microclient import LargeSegmentDefinitionMicroClient
18+
from splitapiclient.microclients.rule_based_segment_microclient import RuleBasedSegmentMicroClient
19+
from splitapiclient.microclients.rule_based_segment_definition_microclient import RuleBasedSegmentDefinitionMicroClient

0 commit comments

Comments
 (0)