Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Changelog

## Unreleased

- Re-exported Protocol Buffer types including `ConfigValue`, `StringList`, `ProtoContext`, `ContextSet`, `ContextShape`, `LogLevel`, `Json`, and `Schema` for easier access.

## [0.11.2] - 2025-02-24

- Updates ConfigValueType's union to include dict to better support json values [#117]
- Renamed encrypted content paths

## [0.11.1] - 2025-02-20

Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,23 @@ result = prefab_cloud_python.get_client().enabled("my-first-feature-flag", conte
print("my-first-feature-flag is:", result)
```

## Protocol Buffer Types

If you need to work with the underlying Protocol Buffer types, the following are re-exported for convenience:

```python
from prefab_cloud_python import ConfigValue, StringList, ProtoContext, ContextSet, ContextShape, LogLevel, Json, Schema

# Create a config value
config_value = ConfigValue(string="example value")

# Create a JSON value
json_value = ConfigValue(json=Json(json='{"key": "value"}'))

# Create a Schema value
schema_value = Schema(definition='{"type": "object", "properties": {"name": {"type": "string"}}}')
```

See full documentation https://docs.prefab.cloud/docs/sdks/python

## Development
Expand Down
14 changes: 14 additions & 0 deletions prefab.proto
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ message ConfigValue {
Provided provided = 12;
IsoDuration duration = 15;
Json json = 16;
Schema schema = 17;
}
optional bool confidential = 13; // don't log or telemetry this value
optional string decrypt_with = 14; // key name to decrypt with
Expand Down Expand Up @@ -91,6 +92,7 @@ enum ConfigType {
SEGMENT = 4;
LIMIT_DEFINITION = 5;
DELETED = 6;
SCHEMA = 7;
}

message Config {
Expand All @@ -104,6 +106,7 @@ message Config {
optional int64 draft_id = 8;
ValueType value_type = 9;
bool send_to_client_sdk = 10; // default value of a boolean in proto3 is false
optional string schema_key = 11;

enum ValueType {
NOT_SET_VALUE_TYPE = 0; // proto null
Expand Down Expand Up @@ -464,3 +467,14 @@ message ClientStats {
int64 end = 2;
uint64 dropped_event_count = 3;
}


message Schema {
enum SchemaType {
UNKNOWN = 0;
ZOD = 1;
JSON_SCHEMA = 2;
}
string schema = 1;
SchemaType schema_type = 2;
}
34 changes: 34 additions & 0 deletions prefab_cloud_python/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
"""
Prefab Cloud Python client library.

This module provides access to the Prefab Cloud configuration and feature flag service.

Main components:
- Client: The main client for interacting with Prefab Cloud
- Options: Configuration options for the client
- Context: Context information for evaluating configs and feature flags

Re-exported Protocol Buffer types:
- ConfigValue: Represents a configuration value
- StringList: Represents a list of strings
- ProtoContext: Protocol buffer Context class
- ContextSet: Collection of contexts
- ContextShape: Shape information for contexts
- LogLevel: Enumeration of log levels
- Json: Represents JSON data in configuration values
- Schema: Represents schema validation for configuration values
"""

from typing import Optional

from . import _internal_logging
Expand All @@ -10,6 +31,19 @@
from .feature_flag_client import FeatureFlagClient
from .config_client import ConfigClient

# Re-export Protocol Buffer types for easier access
import prefab_pb2
from prefab_pb2 import (
ConfigValue,
StringList,
Context as ProtoContext,
ContextSet,
ContextShape,
LogLevel,
Json,
Schema,
)

log = _internal_logging.InternalLogger(__name__)


Expand Down
264 changes: 134 additions & 130 deletions prefab_pb2.py

Large diffs are not rendered by default.

55 changes: 50 additions & 5 deletions prefab_pb2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class _ConfigTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._Enu
SEGMENT: _ConfigType.ValueType # 4
LIMIT_DEFINITION: _ConfigType.ValueType # 5
DELETED: _ConfigType.ValueType # 6
SCHEMA: _ConfigType.ValueType # 7

class ConfigType(_ConfigType, metaclass=_ConfigTypeEnumTypeWrapper): ...

Expand All @@ -58,6 +59,7 @@ LOG_LEVEL: ConfigType.ValueType # 3
SEGMENT: ConfigType.ValueType # 4
LIMIT_DEFINITION: ConfigType.ValueType # 5
DELETED: ConfigType.ValueType # 6
SCHEMA: ConfigType.ValueType # 7
global___ConfigType = ConfigType

class _LogLevel:
Expand Down Expand Up @@ -150,6 +152,7 @@ class ConfigValue(google.protobuf.message.Message):
PROVIDED_FIELD_NUMBER: builtins.int
DURATION_FIELD_NUMBER: builtins.int
JSON_FIELD_NUMBER: builtins.int
SCHEMA_FIELD_NUMBER: builtins.int
CONFIDENTIAL_FIELD_NUMBER: builtins.int
DECRYPT_WITH_FIELD_NUMBER: builtins.int
int: builtins.int
Expand All @@ -172,6 +175,8 @@ class ConfigValue(google.protobuf.message.Message):
def duration(self) -> global___IsoDuration: ...
@property
def json(self) -> global___Json: ...
@property
def schema(self) -> global___Schema: ...
confidential: builtins.bool
"""don't log or telemetry this value"""
decrypt_with: builtins.str
Expand All @@ -192,17 +197,18 @@ class ConfigValue(google.protobuf.message.Message):
provided: global___Provided | None = ...,
duration: global___IsoDuration | None = ...,
json: global___Json | None = ...,
schema: global___Schema | None = ...,
confidential: builtins.bool | None = ...,
decrypt_with: builtins.str | None = ...,
) -> None: ...
def HasField(self, field_name: typing_extensions.Literal["_confidential", b"_confidential", "_decrypt_with", b"_decrypt_with", "bool", b"bool", "bytes", b"bytes", "confidential", b"confidential", "decrypt_with", b"decrypt_with", "double", b"double", "duration", b"duration", "int", b"int", "int_range", b"int_range", "json", b"json", "limit_definition", b"limit_definition", "log_level", b"log_level", "provided", b"provided", "string", b"string", "string_list", b"string_list", "type", b"type", "weighted_values", b"weighted_values"]) -> builtins.bool: ...
def ClearField(self, field_name: typing_extensions.Literal["_confidential", b"_confidential", "_decrypt_with", b"_decrypt_with", "bool", b"bool", "bytes", b"bytes", "confidential", b"confidential", "decrypt_with", b"decrypt_with", "double", b"double", "duration", b"duration", "int", b"int", "int_range", b"int_range", "json", b"json", "limit_definition", b"limit_definition", "log_level", b"log_level", "provided", b"provided", "string", b"string", "string_list", b"string_list", "type", b"type", "weighted_values", b"weighted_values"]) -> None: ...
def HasField(self, field_name: typing_extensions.Literal["_confidential", b"_confidential", "_decrypt_with", b"_decrypt_with", "bool", b"bool", "bytes", b"bytes", "confidential", b"confidential", "decrypt_with", b"decrypt_with", "double", b"double", "duration", b"duration", "int", b"int", "int_range", b"int_range", "json", b"json", "limit_definition", b"limit_definition", "log_level", b"log_level", "provided", b"provided", "schema", b"schema", "string", b"string", "string_list", b"string_list", "type", b"type", "weighted_values", b"weighted_values"]) -> builtins.bool: ...
def ClearField(self, field_name: typing_extensions.Literal["_confidential", b"_confidential", "_decrypt_with", b"_decrypt_with", "bool", b"bool", "bytes", b"bytes", "confidential", b"confidential", "decrypt_with", b"decrypt_with", "double", b"double", "duration", b"duration", "int", b"int", "int_range", b"int_range", "json", b"json", "limit_definition", b"limit_definition", "log_level", b"log_level", "provided", b"provided", "schema", b"schema", "string", b"string", "string_list", b"string_list", "type", b"type", "weighted_values", b"weighted_values"]) -> None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing_extensions.Literal["_confidential", b"_confidential"]) -> typing_extensions.Literal["confidential"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing_extensions.Literal["_decrypt_with", b"_decrypt_with"]) -> typing_extensions.Literal["decrypt_with"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing_extensions.Literal["type", b"type"]) -> typing_extensions.Literal["int", "string", "bytes", "double", "bool", "weighted_values", "limit_definition", "log_level", "string_list", "int_range", "provided", "duration", "json"] | None: ...
def WhichOneof(self, oneof_group: typing_extensions.Literal["type", b"type"]) -> typing_extensions.Literal["int", "string", "bytes", "double", "bool", "weighted_values", "limit_definition", "log_level", "string_list", "int_range", "provided", "duration", "json", "schema"] | None: ...

global___ConfigValue = ConfigValue

Expand Down Expand Up @@ -456,6 +462,7 @@ class Config(google.protobuf.message.Message):
DRAFT_ID_FIELD_NUMBER: builtins.int
VALUE_TYPE_FIELD_NUMBER: builtins.int
SEND_TO_CLIENT_SDK_FIELD_NUMBER: builtins.int
SCHEMA_KEY_FIELD_NUMBER: builtins.int
id: builtins.int
project_id: builtins.int
key: builtins.str
Expand All @@ -470,6 +477,7 @@ class Config(google.protobuf.message.Message):
value_type: global___Config.ValueType.ValueType
send_to_client_sdk: builtins.bool
"""default value of a boolean in proto3 is false"""
schema_key: builtins.str
def __init__(
self,
*,
Expand All @@ -483,10 +491,14 @@ class Config(google.protobuf.message.Message):
draft_id: builtins.int | None = ...,
value_type: global___Config.ValueType.ValueType = ...,
send_to_client_sdk: builtins.bool = ...,
schema_key: builtins.str | None = ...,
) -> None: ...
def HasField(self, field_name: typing_extensions.Literal["_draft_id", b"_draft_id", "changed_by", b"changed_by", "draft_id", b"draft_id"]) -> builtins.bool: ...
def ClearField(self, field_name: typing_extensions.Literal["_draft_id", b"_draft_id", "allowable_values", b"allowable_values", "changed_by", b"changed_by", "config_type", b"config_type", "draft_id", b"draft_id", "id", b"id", "key", b"key", "project_id", b"project_id", "rows", b"rows", "send_to_client_sdk", b"send_to_client_sdk", "value_type", b"value_type"]) -> None: ...
def HasField(self, field_name: typing_extensions.Literal["_draft_id", b"_draft_id", "_schema_key", b"_schema_key", "changed_by", b"changed_by", "draft_id", b"draft_id", "schema_key", b"schema_key"]) -> builtins.bool: ...
def ClearField(self, field_name: typing_extensions.Literal["_draft_id", b"_draft_id", "_schema_key", b"_schema_key", "allowable_values", b"allowable_values", "changed_by", b"changed_by", "config_type", b"config_type", "draft_id", b"draft_id", "id", b"id", "key", b"key", "project_id", b"project_id", "rows", b"rows", "schema_key", b"schema_key", "send_to_client_sdk", b"send_to_client_sdk", "value_type", b"value_type"]) -> None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing_extensions.Literal["_draft_id", b"_draft_id"]) -> typing_extensions.Literal["draft_id"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing_extensions.Literal["_schema_key", b"_schema_key"]) -> typing_extensions.Literal["schema_key"] | None: ...

global___Config = Config

Expand Down Expand Up @@ -1725,3 +1737,36 @@ class ClientStats(google.protobuf.message.Message):
def ClearField(self, field_name: typing_extensions.Literal["dropped_event_count", b"dropped_event_count", "end", b"end", "start", b"start"]) -> None: ...

global___ClientStats = ClientStats

@typing_extensions.final
class Schema(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor

class _SchemaType:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType

class _SchemaTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Schema._SchemaType.ValueType], builtins.type): # noqa: F821
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
UNKNOWN: Schema._SchemaType.ValueType # 0
ZOD: Schema._SchemaType.ValueType # 1
JSON_SCHEMA: Schema._SchemaType.ValueType # 2

class SchemaType(_SchemaType, metaclass=_SchemaTypeEnumTypeWrapper): ...
UNKNOWN: Schema.SchemaType.ValueType # 0
ZOD: Schema.SchemaType.ValueType # 1
JSON_SCHEMA: Schema.SchemaType.ValueType # 2

SCHEMA_FIELD_NUMBER: builtins.int
SCHEMA_TYPE_FIELD_NUMBER: builtins.int
schema: builtins.str
schema_type: global___Schema.SchemaType.ValueType
def __init__(
self,
*,
schema: builtins.str = ...,
schema_type: global___Schema.SchemaType.ValueType = ...,
) -> None: ...
def ClearField(self, field_name: typing_extensions.Literal["schema", b"schema", "schema_type", b"schema_type"]) -> None: ...

global___Schema = Schema
1 change: 1 addition & 0 deletions tests/test_context_shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def test_mapping_is_exhaustive(self):
"confidential",
"decrypt_with",
"duration",
"schema",
]

supported = list(
Expand Down
Loading