Skip to content

Commit 7ef691f

Browse files
authored
Merge pull request #21 from splitio/flag-sets-and-impressions-disabled
Flag sets and impressions disabled and large segments
2 parents 701fa51 + d362ab0 commit 7ef691f

29 files changed

+1591
-20
lines changed

CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,5 @@
3737
- Added ability to retrieve API keys when creating an environment
3838
3.1.13 (Jan 31, 2024)
3939
- Updated keyId of an API KEY to be the actual ID and not the key itself
40+
3.2.0 (Feb 2, 2025)
41+
- Updated to support flag sets, large segments and the impressionsDisabled boolean value

pyproject.toml

Lines changed: 5 additions & 5 deletions
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.1.13"
7+
version = "3.2.0"
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",
@@ -16,13 +16,13 @@ classifiers = [
1616
"Topic :: Software Development :: Libraries",
1717
]
1818
authors = [
19-
{name = "Patricio Echague", email = "pato@split.io"},
19+
{name = "Patricio Echague", email = "patricio.echague@harness.io"},
2020
{name = "Sebastian Arrubia", email = "[email protected]"},
21-
{name = "Martin Redolatti", email = "martin@split.io"},
22-
{name = "Bilal Al-Shawany", email = "bilal@split.io"},
21+
{name = "Martin Redolatti", email = "martin.redolatti@harness.io"},
22+
{name = "Bilal Al-Shawany", email = "bilal.al-shahwany@harness.io"},
2323
]
2424
maintainers = [
25-
{name = "Josh Klein", email = "joshua.klein@split.io"}
25+
{name = "Josh Klein", email = "joshua.klein@harness.io"}
2626
]
2727
dependencies = [
2828
'argparse >= 1.1',

splitapiclient/http_clients/base_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def get_params_from_url_template(url):
5252
5353
:rtype: list.
5454
'''
55-
regex = '{([\w-]+)}*'
55+
regex = r'{([\w-]+)}*'
5656
url_params = re.findall(regex, url)
5757
return list(set(url_params)) if url_params else []
5858

splitapiclient/http_clients/sync_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def make_request(self, endpoint, body=None, **kwargs):
109109
else:
110110
break
111111

112-
if not (response.status_code == 200 or response.status_code == 204):
112+
if not (response.status_code == 200 or response.status_code == 204 or response.status_code == 201):
113113
LOGGER.warning('RESPONSE CODE: %s' % response.status_code)
114114
self._handle_invalid_response(response)
115115

splitapiclient/main/sync_apiclient.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@
1717
from splitapiclient.microclients import GroupMicroClient
1818
from splitapiclient.microclients import APIKeyMicroClient
1919
from splitapiclient.microclients import RestrictionMicroClient
20+
from splitapiclient.microclients import FlagSetMicroClient
21+
from splitapiclient.microclients import LargeSegmentMicroClient
22+
from splitapiclient.microclients import LargeSegmentDefinitionMicroClient
2023

2124

2225
class SyncApiClient(BaseApiClient):
2326
'''
2427
Synchronous Split API client
2528
'''
26-
29+
BASE_PROD_URL_V3 = 'https://api.split.io/api/v3'
2730
BASE_PROD_URL = 'https://api.split.io/internal/api/v2'
2831
BASE_PROD_URL_OLD = 'https://api.split.io/internal/api/v1'
2932

@@ -41,6 +44,11 @@ def __init__(self, config):
4144
else:
4245
self._base_url = self.BASE_PROD_URL
4346
self._base_url_old = self.BASE_PROD_URL_OLD
47+
48+
if 'base_url_v3' in config:
49+
self._base_url_v3 = config['base_url_v3']
50+
else:
51+
self._base_url_v3 = self.BASE_PROD_URL_V3
4452

4553
missing = [i for i in ['apikey'] if i not in config]
4654
if missing:
@@ -52,11 +60,15 @@ def __init__(self, config):
5260
self._apikey = config['apikey']
5361

5462
http_client = SyncHttpClient(self._base_url, self._apikey)
63+
http_clientv3 = SyncHttpClient(self._base_url_v3, self._apikey)
64+
5565
self._environment_client = EnvironmentMicroClient(http_client)
5666
self._split_client = SplitMicroClient(http_client)
5767
self._split_definition_client = SplitDefinitionMicroClient(http_client)
5868
self._segment_client = SegmentMicroClient(http_client)
5969
self._segment_definition_client = SegmentDefinitionMicroClient(http_client)
70+
self._large_segment_client = LargeSegmentMicroClient(http_client)
71+
self._large_segment_definition_client = LargeSegmentDefinitionMicroClient(http_client)
6072
self._workspace_client = WorkspaceMicroClient(http_client)
6173
self._traffic_type_client = TrafficTypeMicroClient(http_client)
6274
self._attribute_client = AttributeMicroClient(http_client)
@@ -66,6 +78,7 @@ def __init__(self, config):
6678
self._group_client = GroupMicroClient(http_client)
6779
self._apikey_client = APIKeyMicroClient(http_client)
6880
self._restriction_client = RestrictionMicroClient(http_client)
81+
self._flag_set_client = FlagSetMicroClient(http_clientv3)
6982

7083
@property
7184
def traffic_types(self):
@@ -90,6 +103,14 @@ def segments(self):
90103
@property
91104
def segment_definitions(self):
92105
return self._segment_definition_client
106+
107+
@property
108+
def large_segments(self):
109+
return self._large_segment_client
110+
111+
@property
112+
def large_segment_definitions(self):
113+
return self._large_segment_definition_client
93114

94115
@property
95116
def workspaces(self):
@@ -122,3 +143,7 @@ def apikeys(self):
122143
@property
123144
def restrictions(self):
124145
return self._restriction_client
146+
147+
@property
148+
def flag_sets(self):
149+
return self._flag_set_client

splitapiclient/microclients/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@
1212
from splitapiclient.microclients.group_microclient import GroupMicroClient
1313
from splitapiclient.microclients.apikey_microclient import APIKeyMicroClient
1414
from splitapiclient.microclients.restriction_microclient import RestrictionMicroClient
15+
from splitapiclient.microclients.flag_set_microclient import FlagSetMicroClient
16+
from splitapiclient.microclients.large_segment_microclient import LargeSegmentMicroClient
17+
from splitapiclient.microclients.large_segment_definition_microclient import LargeSegmentDefinitionMicroClient
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
from splitapiclient.resources.flag_set import FlagSet
2+
from splitapiclient.util.exceptions import HTTPResponseError, \
3+
UnknownApiClientError
4+
from splitapiclient.util.logger import LOGGER
5+
from splitapiclient.util.helpers import as_dict
6+
7+
8+
class FlagSetMicroClient:
9+
'''
10+
'''
11+
_endpoint = {
12+
'list_initial': {
13+
'method': 'GET',
14+
'url_template': 'flag-sets?workspace_id={workspace_id}&limit=50',
15+
'headers': [{
16+
'name': 'Authorization',
17+
'template': 'Bearer {value}',
18+
'required': True,
19+
}],
20+
'query_string': [],
21+
'response': True,
22+
},
23+
'list_next': {
24+
'method': 'GET',
25+
'url_template': 'flag-sets?workspace_id={workspace_id}&after={after}&limit=50',
26+
'headers': [{
27+
'name': 'Authorization',
28+
'template': 'Bearer {value}',
29+
'required': True,
30+
}],
31+
'query_string': [],
32+
'response': True,
33+
},
34+
'get': {
35+
'method': 'GET',
36+
'url_template': 'flag-sets/{flag_set_id}',
37+
'headers': [{
38+
'name': 'Authorization',
39+
'template': 'Bearer {value}',
40+
'required': True,
41+
}],
42+
'query_string': [],
43+
'response': True,
44+
},
45+
'create': {
46+
'method': 'POST',
47+
'url_template': 'flag-sets',
48+
'headers': [{
49+
'name': 'Authorization',
50+
'template': 'Bearer {value}',
51+
'required': True,
52+
}],
53+
'query_string': [],
54+
'response': True,
55+
},
56+
'delete': {
57+
'method': 'DELETE',
58+
'url_template': ('flag-sets/{flagSetId}'),
59+
'headers': [{
60+
'name': 'Authorization',
61+
'template': 'Bearer {value}',
62+
'required': True,
63+
}],
64+
'query_string': [],
65+
'response': True,
66+
},
67+
}
68+
69+
def __init__(self, http_client):
70+
'''
71+
Constructor
72+
'''
73+
self._http_client = http_client
74+
75+
def list(self, workspace_id):
76+
'''
77+
Returns a list of flag_sets objects.
78+
79+
:returns: list of flag_sets objects
80+
:rtype: list(flag_sets)
81+
'''
82+
final_list = []
83+
afterMarker = 0
84+
while True:
85+
if afterMarker==0:
86+
response = self._http_client.make_request(
87+
self._endpoint['list_initial'],
88+
workspace_id = workspace_id
89+
)
90+
else:
91+
response = self._http_client.make_request(
92+
self._endpoint['list_next'],
93+
workspace_id = workspace_id,
94+
after = afterMarker
95+
)
96+
for item in response['data']:
97+
final_list.append(as_dict(item))
98+
if response['nextMarker'] is None:
99+
break
100+
else:
101+
afterMarker = response['nextMarker']
102+
continue
103+
return [FlagSet(item, workspace_id, self._http_client) for item in final_list]
104+
105+
def find(self, flag_set_name=None, workspace_id=None):
106+
'''
107+
Search for flag_set in list of flag_sets objects.
108+
109+
:returns: flag_set object
110+
:rtype: flag_set
111+
'''
112+
113+
for item in self.list(workspace_id=workspace_id):
114+
if item.name==flag_set_name:
115+
return item
116+
LOGGER.error("flag_set Name does not exist")
117+
return None
118+
119+
def get(self, flag_set_id=None):
120+
'''
121+
get a flag_set
122+
123+
:param flag_set_id: flag_set id
124+
:returns: flag_set
125+
:rtype: flag_set
126+
'''
127+
128+
response = self._http_client.make_request(
129+
self._endpoint['get'],
130+
flag_set_id=flag_set_id
131+
)
132+
return FlagSet(data=response, client=self._http_client)
133+
134+
135+
136+
137+
def add(self, flag_set, workspace_id):
138+
'''
139+
add a flag_set
140+
141+
:param flag_set: flag_set instance
142+
:returns: newly created flag_set
143+
:rtype: flag_set
144+
'''
145+
data = as_dict(flag_set)
146+
data['workspace'] = {
147+
'id': workspace_id,
148+
'type': 'WORKSPACE'
149+
}
150+
response = self._http_client.make_request(
151+
self._endpoint['create'],
152+
body=data
153+
)
154+
return FlagSet(response, workspace_id, self._http_client)
155+
156+
157+
158+
def delete(self, flag_set_id ):
159+
'''
160+
delete a flag_set
161+
162+
:param flag_set id:
163+
164+
:returns:
165+
:rtype: True if successful
166+
'''
167+
response = self._http_client.make_request(
168+
self._endpoint['delete'],
169+
flagSetId =flag_set_id,
170+
)
171+
return response

0 commit comments

Comments
 (0)