flipt 1.3.0__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.
- flipt/__init__.py +7 -0
- flipt/async_client.py +21 -0
- flipt/authentication/__init__.py +19 -0
- flipt/evaluation/__init__.py +29 -0
- flipt/evaluation/async_evaluation_client.py +69 -0
- flipt/evaluation/models.py +75 -0
- flipt/evaluation/sync_evaluation_client.py +69 -0
- flipt/exceptions.py +14 -0
- flipt/flags/__init__.py +15 -0
- flipt/flags/async_flag_client.py +52 -0
- flipt/flags/models.py +37 -0
- flipt/flags/sync_flag_client.py +52 -0
- flipt/models.py +24 -0
- flipt/py.typed +0 -0
- flipt/sync_client.py +21 -0
- flipt-1.3.0.dist-info/METADATA +64 -0
- flipt-1.3.0.dist-info/RECORD +19 -0
- flipt-1.3.0.dist-info/WHEEL +4 -0
- flipt-1.3.0.dist-info/entry_points.txt +3 -0
flipt/__init__.py
ADDED
flipt/async_client.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
|
|
3
|
+
from .authentication import AuthenticationStrategy
|
|
4
|
+
from .evaluation import AsyncEvaluation
|
|
5
|
+
from .flags import AsyncFlag
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AsyncFliptClient:
|
|
9
|
+
def __init__(
|
|
10
|
+
self,
|
|
11
|
+
url: str = "http://localhost:8080",
|
|
12
|
+
timeout: int = 60,
|
|
13
|
+
authentication: AuthenticationStrategy | None = None,
|
|
14
|
+
):
|
|
15
|
+
self.httpx_client = httpx.AsyncClient(timeout=timeout)
|
|
16
|
+
|
|
17
|
+
self.evaluation = AsyncEvaluation(url, authentication, self.httpx_client)
|
|
18
|
+
self.flag = AsyncFlag(url, authentication, self.httpx_client)
|
|
19
|
+
|
|
20
|
+
async def close(self) -> None:
|
|
21
|
+
await self.httpx_client.aclose()
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class AuthenticationStrategy:
|
|
2
|
+
def authenticate(self, headers: dict[str, str]) -> None:
|
|
3
|
+
raise NotImplementedError
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ClientTokenAuthentication(AuthenticationStrategy):
|
|
7
|
+
def __init__(self, token: str) -> None:
|
|
8
|
+
self.token = token
|
|
9
|
+
|
|
10
|
+
def authenticate(self, headers: dict[str, str]) -> None:
|
|
11
|
+
headers["Authorization"] = f"Bearer {self.token}"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class JWTAuthentication(AuthenticationStrategy):
|
|
15
|
+
def __init__(self, token: str) -> None:
|
|
16
|
+
self.token = token
|
|
17
|
+
|
|
18
|
+
def authenticate(self, headers: dict[str, str]) -> None:
|
|
19
|
+
headers["Authorization"] = f"JWT {self.token}"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from .async_evaluation_client import AsyncEvaluation
|
|
2
|
+
from .models import (
|
|
3
|
+
BatchEvaluationRequest,
|
|
4
|
+
BatchEvaluationResponse,
|
|
5
|
+
BooleanEvaluationResponse,
|
|
6
|
+
ErrorEvaluationReason,
|
|
7
|
+
ErrorEvaluationResponse,
|
|
8
|
+
EvaluationReason,
|
|
9
|
+
EvaluationRequest,
|
|
10
|
+
EvaluationResponse,
|
|
11
|
+
EvaluationResponseType,
|
|
12
|
+
VariantEvaluationResponse,
|
|
13
|
+
)
|
|
14
|
+
from .sync_evaluation_client import Evaluation
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"Evaluation",
|
|
18
|
+
"AsyncEvaluation",
|
|
19
|
+
"EvaluationResponseType",
|
|
20
|
+
"EvaluationReason",
|
|
21
|
+
"ErrorEvaluationReason",
|
|
22
|
+
"EvaluationRequest",
|
|
23
|
+
"BatchEvaluationRequest",
|
|
24
|
+
"VariantEvaluationResponse",
|
|
25
|
+
"BooleanEvaluationResponse",
|
|
26
|
+
"ErrorEvaluationResponse",
|
|
27
|
+
"EvaluationResponse",
|
|
28
|
+
"BatchEvaluationResponse",
|
|
29
|
+
]
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from http import HTTPStatus
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
|
|
5
|
+
from flipt.authentication import AuthenticationStrategy
|
|
6
|
+
from flipt.exceptions import FliptApiError
|
|
7
|
+
|
|
8
|
+
from .models import (
|
|
9
|
+
BatchEvaluationRequest,
|
|
10
|
+
BatchEvaluationResponse,
|
|
11
|
+
BooleanEvaluationResponse,
|
|
12
|
+
EvaluationRequest,
|
|
13
|
+
VariantEvaluationResponse,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AsyncEvaluation:
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
url: str,
|
|
21
|
+
authentication: AuthenticationStrategy | None = None,
|
|
22
|
+
httpx_client: httpx.AsyncClient | None = None,
|
|
23
|
+
):
|
|
24
|
+
self.url = url
|
|
25
|
+
self.headers: dict[str, str] = {}
|
|
26
|
+
|
|
27
|
+
self._client = httpx_client or httpx.AsyncClient()
|
|
28
|
+
|
|
29
|
+
if authentication:
|
|
30
|
+
authentication.authenticate(self.headers)
|
|
31
|
+
|
|
32
|
+
async def close(self) -> None:
|
|
33
|
+
await self._client.aclose()
|
|
34
|
+
|
|
35
|
+
def _raise_on_error(self, response: httpx.Response) -> None:
|
|
36
|
+
if response.status_code != 200:
|
|
37
|
+
body = response.json()
|
|
38
|
+
message = body.get("message", HTTPStatus(response.status_code).description)
|
|
39
|
+
raise FliptApiError(message, response.status_code)
|
|
40
|
+
|
|
41
|
+
async def variant(self, request: EvaluationRequest) -> VariantEvaluationResponse:
|
|
42
|
+
response = await self._client.post(
|
|
43
|
+
f"{self.url}/evaluate/v1/variant",
|
|
44
|
+
headers=self.headers,
|
|
45
|
+
json=request.model_dump(),
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
self._raise_on_error(response)
|
|
49
|
+
return VariantEvaluationResponse.model_validate_json(response.text)
|
|
50
|
+
|
|
51
|
+
async def boolean(self, request: EvaluationRequest) -> BooleanEvaluationResponse:
|
|
52
|
+
response = await self._client.post(
|
|
53
|
+
f"{self.url}/evaluate/v1/boolean",
|
|
54
|
+
headers=self.headers,
|
|
55
|
+
json=request.model_dump(),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
self._raise_on_error(response)
|
|
59
|
+
return BooleanEvaluationResponse.model_validate_json(response.text)
|
|
60
|
+
|
|
61
|
+
async def batch(self, request: BatchEvaluationRequest) -> BatchEvaluationResponse:
|
|
62
|
+
response = await self._client.post(
|
|
63
|
+
f"{self.url}/evaluate/v1/batch",
|
|
64
|
+
headers=self.headers,
|
|
65
|
+
json=request.model_dump(),
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
self._raise_on_error(response)
|
|
69
|
+
return BatchEvaluationResponse.model_validate_json(response.text)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from enum import StrEnum
|
|
2
|
+
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
|
|
5
|
+
from flipt.models import CamelAliasModel
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class EvaluationResponseType(StrEnum):
|
|
9
|
+
VARIANT_EVALUATION_RESPONSE_TYPE = "VARIANT_EVALUATION_RESPONSE_TYPE"
|
|
10
|
+
BOOLEAN_EVALUATION_RESPONSE_TYPE = "BOOLEAN_EVALUATION_RESPONSE_TYPE"
|
|
11
|
+
ERROR_EVALUATION_RESPONSE_TYPE = "ERROR_EVALUATION_RESPONSE_TYPE"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class EvaluationReason(StrEnum):
|
|
15
|
+
UNKNOWN_EVALUATION_REASON = "UNKNOWN_EVALUATION_REASON"
|
|
16
|
+
FLAG_DISABLED_EVALUATION_REASON = "FLAG_DISABLED_EVALUATION_REASON"
|
|
17
|
+
MATCH_EVALUATION_REASON = "MATCH_EVALUATION_REASON"
|
|
18
|
+
DEFAULT_EVALUATION_REASON = "DEFAULT_EVALUATION_REASON"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ErrorEvaluationReason(StrEnum):
|
|
22
|
+
UNKNOWN_ERROR_EVALUATION_REASON = "UNKNOWN_ERROR_EVALUATION_REASON"
|
|
23
|
+
NOT_FOUND_ERROR_EVALUATION_REASON = "NOT_FOUND_ERROR_EVALUATION_REASON"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class EvaluationRequest(CamelAliasModel):
|
|
27
|
+
namespace_key: str = Field(default="default")
|
|
28
|
+
flag_key: str
|
|
29
|
+
entity_id: str
|
|
30
|
+
context: dict
|
|
31
|
+
reference: str | None = None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class BatchEvaluationRequest(CamelAliasModel):
|
|
35
|
+
request_id: str | None = None
|
|
36
|
+
requests: list[EvaluationRequest]
|
|
37
|
+
reference: str | None = None
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class VariantEvaluationResponse(CamelAliasModel):
|
|
41
|
+
match: bool
|
|
42
|
+
segment_keys: list[str]
|
|
43
|
+
reason: EvaluationReason
|
|
44
|
+
flag_key: str
|
|
45
|
+
variant_key: str
|
|
46
|
+
variant_attachment: str
|
|
47
|
+
request_duration_millis: float
|
|
48
|
+
timestamp: str
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class BooleanEvaluationResponse(CamelAliasModel):
|
|
52
|
+
enabled: bool
|
|
53
|
+
flag_key: str
|
|
54
|
+
reason: EvaluationReason
|
|
55
|
+
request_duration_millis: float
|
|
56
|
+
timestamp: str
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ErrorEvaluationResponse(CamelAliasModel):
|
|
60
|
+
flag_key: str
|
|
61
|
+
namespace_key: str
|
|
62
|
+
reason: ErrorEvaluationReason
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class EvaluationResponse(CamelAliasModel):
|
|
66
|
+
type: EvaluationResponseType
|
|
67
|
+
boolean_response: BooleanEvaluationResponse | None = None
|
|
68
|
+
variant_response: VariantEvaluationResponse | None = None
|
|
69
|
+
error_response: ErrorEvaluationResponse | None = None
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class BatchEvaluationResponse(CamelAliasModel):
|
|
73
|
+
request_id: str
|
|
74
|
+
responses: list[EvaluationResponse]
|
|
75
|
+
request_duration_millis: float
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from http import HTTPStatus
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
|
|
5
|
+
from flipt.authentication import AuthenticationStrategy
|
|
6
|
+
from flipt.exceptions import FliptApiError
|
|
7
|
+
|
|
8
|
+
from .models import (
|
|
9
|
+
BatchEvaluationRequest,
|
|
10
|
+
BatchEvaluationResponse,
|
|
11
|
+
BooleanEvaluationResponse,
|
|
12
|
+
EvaluationRequest,
|
|
13
|
+
VariantEvaluationResponse,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Evaluation:
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
url: str,
|
|
21
|
+
authentication: AuthenticationStrategy | None = None,
|
|
22
|
+
httpx_client: httpx.Client | None = None,
|
|
23
|
+
):
|
|
24
|
+
self.url = url
|
|
25
|
+
self.headers: dict[str, str] = {}
|
|
26
|
+
|
|
27
|
+
self._client = httpx_client or httpx.Client()
|
|
28
|
+
|
|
29
|
+
if authentication:
|
|
30
|
+
authentication.authenticate(self.headers)
|
|
31
|
+
|
|
32
|
+
def close(self) -> None:
|
|
33
|
+
self._client.close()
|
|
34
|
+
|
|
35
|
+
def _raise_on_error(self, response: httpx.Response) -> None:
|
|
36
|
+
if response.status_code != 200:
|
|
37
|
+
body = response.json()
|
|
38
|
+
message = body.get("message", HTTPStatus(response.status_code).description)
|
|
39
|
+
raise FliptApiError(message, response.status_code)
|
|
40
|
+
|
|
41
|
+
def variant(self, request: EvaluationRequest) -> VariantEvaluationResponse:
|
|
42
|
+
response = self._client.post(
|
|
43
|
+
f"{self.url}/evaluate/v1/variant",
|
|
44
|
+
headers=self.headers,
|
|
45
|
+
json=request.model_dump(),
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
self._raise_on_error(response)
|
|
49
|
+
return VariantEvaluationResponse.model_validate_json(response.text)
|
|
50
|
+
|
|
51
|
+
def boolean(self, request: EvaluationRequest) -> BooleanEvaluationResponse:
|
|
52
|
+
response = self._client.post(
|
|
53
|
+
f"{self.url}/evaluate/v1/boolean",
|
|
54
|
+
headers=self.headers,
|
|
55
|
+
json=request.model_dump(),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
self._raise_on_error(response)
|
|
59
|
+
return BooleanEvaluationResponse.model_validate_json(response.text)
|
|
60
|
+
|
|
61
|
+
def batch(self, request: BatchEvaluationRequest) -> BatchEvaluationResponse:
|
|
62
|
+
response = self._client.post(
|
|
63
|
+
f"{self.url}/evaluate/v1/batch",
|
|
64
|
+
headers=self.headers,
|
|
65
|
+
json=request.model_dump(),
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
self._raise_on_error(response)
|
|
69
|
+
return BatchEvaluationResponse.model_validate_json(response.text)
|
flipt/exceptions.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class BaseFliptError(Exception):
|
|
2
|
+
pass
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class FliptApiError(BaseFliptError):
|
|
6
|
+
message: str
|
|
7
|
+
status_code: int
|
|
8
|
+
|
|
9
|
+
def __init__(self, message: str, status_code: int):
|
|
10
|
+
self.message = message
|
|
11
|
+
self.status_code = status_code
|
|
12
|
+
|
|
13
|
+
def __repr__(self) -> str:
|
|
14
|
+
return f"<FliptApiError(message={self.message}, status_code={self.status_code})>"
|
flipt/flags/__init__.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .async_flag_client import AsyncFlag
|
|
2
|
+
from .models import (
|
|
3
|
+
Flag,
|
|
4
|
+
FlagType,
|
|
5
|
+
ListFlagsResponse,
|
|
6
|
+
)
|
|
7
|
+
from .sync_flag_client import SyncFlag
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"AsyncFlag",
|
|
11
|
+
"SyncFlag",
|
|
12
|
+
"ListFlagsResponse",
|
|
13
|
+
"Flag",
|
|
14
|
+
"FlagType",
|
|
15
|
+
]
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from http import HTTPStatus
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
|
|
5
|
+
from flipt.authentication import AuthenticationStrategy
|
|
6
|
+
from flipt.exceptions import FliptApiError
|
|
7
|
+
from flipt.models import CommonParameters, ListParameters
|
|
8
|
+
|
|
9
|
+
from .models import Flag, ListFlagsResponse
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AsyncFlag:
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
url: str,
|
|
16
|
+
authentication: AuthenticationStrategy | None = None,
|
|
17
|
+
httpx_client: httpx.AsyncClient | None = None,
|
|
18
|
+
):
|
|
19
|
+
self.url = url
|
|
20
|
+
self.headers: dict[str, str] = {}
|
|
21
|
+
|
|
22
|
+
self._client = httpx_client or httpx.AsyncClient()
|
|
23
|
+
|
|
24
|
+
if authentication:
|
|
25
|
+
authentication.authenticate(self.headers)
|
|
26
|
+
|
|
27
|
+
async def close(self) -> None:
|
|
28
|
+
await self._client.aclose()
|
|
29
|
+
|
|
30
|
+
def _raise_on_error(self, response: httpx.Response) -> None:
|
|
31
|
+
if response.status_code != 200:
|
|
32
|
+
body = response.json()
|
|
33
|
+
message = body.get("message", HTTPStatus(response.status_code).description)
|
|
34
|
+
raise FliptApiError(message, response.status_code)
|
|
35
|
+
|
|
36
|
+
async def list_flags(self, namespace_key: str, params: ListParameters | None = None) -> ListFlagsResponse:
|
|
37
|
+
response = await self._client.get(
|
|
38
|
+
f"{self.url}/api/v1/namespaces/{namespace_key}/flags",
|
|
39
|
+
params=params.model_dump_json(exclude_none=True, by_alias=True) if params else {},
|
|
40
|
+
headers=self.headers,
|
|
41
|
+
)
|
|
42
|
+
self._raise_on_error(response)
|
|
43
|
+
return ListFlagsResponse.model_validate_json(response.text)
|
|
44
|
+
|
|
45
|
+
async def get_flag(self, namespace_key: str, flag_key: str, params: CommonParameters | None = None) -> Flag:
|
|
46
|
+
response = await self._client.get(
|
|
47
|
+
f"{self.url}/api/v1/namespaces/{namespace_key}/flags/{flag_key}",
|
|
48
|
+
params=params.model_dump_json(exclude_none=True, by_alias=True) if params else {},
|
|
49
|
+
headers=self.headers,
|
|
50
|
+
)
|
|
51
|
+
self._raise_on_error(response)
|
|
52
|
+
return Flag.model_validate_json(response.text)
|
flipt/flags/models.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from enum import StrEnum
|
|
3
|
+
|
|
4
|
+
from flipt.models import CamelAliasModel, PaginatedResponse
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class FlagType(StrEnum):
|
|
8
|
+
variant = "VARIANT_FLAG_TYPE"
|
|
9
|
+
boolean = "BOOLEAN_FLAG_TYPE"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Variant(CamelAliasModel):
|
|
13
|
+
attachment: str
|
|
14
|
+
description: str
|
|
15
|
+
flag_key: str
|
|
16
|
+
id: str
|
|
17
|
+
key: str
|
|
18
|
+
name: str
|
|
19
|
+
namespace_key: str
|
|
20
|
+
created_at: datetime
|
|
21
|
+
updated_at: datetime
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Flag(CamelAliasModel):
|
|
25
|
+
key: str
|
|
26
|
+
name: str
|
|
27
|
+
description: str
|
|
28
|
+
enabled: bool
|
|
29
|
+
namespace_key: str
|
|
30
|
+
type: FlagType
|
|
31
|
+
created_at: datetime
|
|
32
|
+
updated_at: datetime
|
|
33
|
+
variants: list[Variant]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ListFlagsResponse(PaginatedResponse):
|
|
37
|
+
flags: list[Flag]
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from http import HTTPStatus
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
|
|
5
|
+
from flipt.authentication import AuthenticationStrategy
|
|
6
|
+
from flipt.exceptions import FliptApiError
|
|
7
|
+
from flipt.models import CommonParameters, ListParameters
|
|
8
|
+
|
|
9
|
+
from .models import Flag, ListFlagsResponse
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SyncFlag:
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
url: str,
|
|
16
|
+
authentication: AuthenticationStrategy | None = None,
|
|
17
|
+
httpx_client: httpx.Client | None = None,
|
|
18
|
+
):
|
|
19
|
+
self.url = url
|
|
20
|
+
self.headers: dict[str, str] = {}
|
|
21
|
+
|
|
22
|
+
self._client = httpx_client or httpx.Client()
|
|
23
|
+
|
|
24
|
+
if authentication:
|
|
25
|
+
authentication.authenticate(self.headers)
|
|
26
|
+
|
|
27
|
+
def close(self) -> None:
|
|
28
|
+
self._client.close()
|
|
29
|
+
|
|
30
|
+
def _raise_on_error(self, response: httpx.Response) -> None:
|
|
31
|
+
if response.status_code != 200:
|
|
32
|
+
body = response.json()
|
|
33
|
+
message = body.get("message", HTTPStatus(response.status_code).description)
|
|
34
|
+
raise FliptApiError(message, response.status_code)
|
|
35
|
+
|
|
36
|
+
def list_flags(self, namespace_key: str, params: ListParameters | None = None) -> ListFlagsResponse:
|
|
37
|
+
response = self._client.get(
|
|
38
|
+
f"{self.url}/api/v1/namespaces/{namespace_key}/flags",
|
|
39
|
+
params=params.model_dump_json(exclude_none=True, by_alias=True) if params else {},
|
|
40
|
+
headers=self.headers,
|
|
41
|
+
)
|
|
42
|
+
self._raise_on_error(response)
|
|
43
|
+
return ListFlagsResponse.model_validate_json(response.text)
|
|
44
|
+
|
|
45
|
+
def get_flag(self, namespace_key: str, flag_key: str, params: CommonParameters | None = None) -> Flag:
|
|
46
|
+
response = self._client.get(
|
|
47
|
+
f"{self.url}/api/v1/namespaces/{namespace_key}/flags/{flag_key}",
|
|
48
|
+
params=params.model_dump_json(exclude_none=True, by_alias=True) if params else {},
|
|
49
|
+
headers=self.headers,
|
|
50
|
+
)
|
|
51
|
+
self._raise_on_error(response)
|
|
52
|
+
return Flag.model_validate_json(response.text)
|
flipt/models.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from pydantic import AliasGenerator, BaseModel, ConfigDict
|
|
2
|
+
from pydantic.alias_generators import to_camel
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CamelAliasModel(BaseModel):
|
|
6
|
+
model_config = ConfigDict(
|
|
7
|
+
alias_generator=AliasGenerator(alias=to_camel),
|
|
8
|
+
populate_by_name=True,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CommonParameters(CamelAliasModel):
|
|
13
|
+
reference: str | None = None
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ListParameters(CommonParameters):
|
|
17
|
+
limit: int | None = None
|
|
18
|
+
offset: int | None = None
|
|
19
|
+
page_token: str | None = None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class PaginatedResponse(CamelAliasModel):
|
|
23
|
+
next_page_token: str
|
|
24
|
+
total_count: int
|
flipt/py.typed
ADDED
|
File without changes
|
flipt/sync_client.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
|
|
3
|
+
from .authentication import AuthenticationStrategy
|
|
4
|
+
from .evaluation import Evaluation
|
|
5
|
+
from .flags import SyncFlag
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class FliptClient:
|
|
9
|
+
def __init__(
|
|
10
|
+
self,
|
|
11
|
+
url: str = "http://localhost:8080",
|
|
12
|
+
timeout: int = 60,
|
|
13
|
+
authentication: AuthenticationStrategy | None = None,
|
|
14
|
+
):
|
|
15
|
+
self.httpx_client = httpx.Client(timeout=timeout)
|
|
16
|
+
|
|
17
|
+
self.evaluation = Evaluation(url, authentication, self.httpx_client)
|
|
18
|
+
self.flag = SyncFlag(url, authentication, self.httpx_client)
|
|
19
|
+
|
|
20
|
+
def close(self) -> None:
|
|
21
|
+
self.httpx_client.close()
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: flipt
|
|
3
|
+
Version: 1.3.0
|
|
4
|
+
Summary: Flipt Server SDK
|
|
5
|
+
License: MIT
|
|
6
|
+
Author: Flipt Devs
|
|
7
|
+
Author-email: dev@flipt.io
|
|
8
|
+
Requires-Python: >=3.11,<4.0
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Requires-Dist: httpx (>=0.27.0,<0.28.0)
|
|
14
|
+
Requires-Dist: pydantic (>=2.5.3,<3.0.0)
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# Flipt Python
|
|
18
|
+
|
|
19
|
+
[](https://pypi.org/project/flipt)
|
|
20
|
+
|
|
21
|
+
This directory contains the Python source code for the Flipt [server-side](https://www.flipt.io/docs/integration/server/rest) client.
|
|
22
|
+
|
|
23
|
+
## Documentation
|
|
24
|
+
|
|
25
|
+
API documentation is available at <https://www.flipt.io/docs/reference/overview>.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
pip install flipt=={version}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
In your Python code you can import this client and use it as so:
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from flipt import FliptClient
|
|
39
|
+
from flipt.evaluation import BatchEvaluationRequest, EvaluationRequest
|
|
40
|
+
|
|
41
|
+
flipt_client = FliptClient()
|
|
42
|
+
|
|
43
|
+
variant_flag = flipt_client.evaluation.variant(
|
|
44
|
+
EvaluationRequest(
|
|
45
|
+
namespace_key="default",
|
|
46
|
+
flag_key="flagll",
|
|
47
|
+
entity_id="entity",
|
|
48
|
+
context={"fizz": "buzz"},
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
print(variant_flag)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
There is a more detailed example in the [examples](./examples) directory.
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
## For developers
|
|
59
|
+
|
|
60
|
+
After adding new code, please don't forget to add unit tests for new features.
|
|
61
|
+
To format the code, check it with linters and run tests, use the `make check` command.
|
|
62
|
+
|
|
63
|
+
Please keep the Python [PEP8](https://peps.python.org/pep-0008/) in mind while adding new code.
|
|
64
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
flipt/__init__.py,sha256=lejYXHyiOU4aFbw2Hu7h2QytrxlGyWjofbUZAKBx9Mw,138
|
|
2
|
+
flipt/async_client.py,sha256=9Du6gIOM1gV2ojZ_wocMVD9KGY6E5stLdTq-Wzv2jws,625
|
|
3
|
+
flipt/authentication/__init__.py,sha256=_DOHmgWYQVLxtJ91kiQ8m-C6z7wuKyqIiPJe69DgfpE,614
|
|
4
|
+
flipt/evaluation/__init__.py,sha256=rDXQHPiww5h3ffISrPdRAWghIQQyxRvaF-Z1aQBlrAw,744
|
|
5
|
+
flipt/evaluation/async_evaluation_client.py,sha256=AZqbw-qehwCGwTigHOv8we-Wowmb7gjqYM6imRQlNXY,2207
|
|
6
|
+
flipt/evaluation/models.py,sha256=xzxSibS52EQ8Q5JmUSPsJrInvUgyLItAeezgXtFzuOw,2108
|
|
7
|
+
flipt/evaluation/sync_evaluation_client.py,sha256=E2bN5Emzm8ZslKWdp79G07hED43CVDzF8YLUU5KRHuc,2143
|
|
8
|
+
flipt/exceptions.py,sha256=8-D9K4yRWRBK0hG9eMehU8Syq4RLfcmHT8E8-j-hl6I,368
|
|
9
|
+
flipt/flags/__init__.py,sha256=94-RL_F8ZKFVfx1DECkM08lvJlHDI2vfHSpXxmSrFfQ,252
|
|
10
|
+
flipt/flags/async_flag_client.py,sha256=ivmInMViYkvKSF-5TrERJ4P_he_yBOVfux2igeuIpMc,1945
|
|
11
|
+
flipt/flags/models.py,sha256=y4SDmaSF3mZOHx-y3au7KzPGXj52PZ6ETCJcMuNUplc,701
|
|
12
|
+
flipt/flags/sync_flag_client.py,sha256=kci-NLNfyYy4RwTG0WSLWbCuXMc19ep9Ri9wsdsZGrg,1897
|
|
13
|
+
flipt/models.py,sha256=oEUte_vQqGzWNOCeQTBFP5MxAWAZEDdkjBVhZLTpDvE,567
|
|
14
|
+
flipt/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
flipt/sync_client.py,sha256=C8SDP1LQ6IgSE2873KdiT5IiagKeinPDrkIa_2szkcE,590
|
|
16
|
+
flipt-1.3.0.dist-info/METADATA,sha256=B_XIaWrs2P2SLFtufcQwqceYCrsdl7gTrw_26bvHBkg,1684
|
|
17
|
+
flipt-1.3.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
18
|
+
flipt-1.3.0.dist-info/entry_points.txt,sha256=d-DgzOMENNfQ2VNMOztEgFpFxFffuOcwGl6KXc-ThuA,37
|
|
19
|
+
flipt-1.3.0.dist-info/RECORD,,
|