gofeatureflag-python-provider 0.4.4__tar.gz → 1.0.0__tar.gz
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.
- gofeatureflag_python_provider-1.0.0/.gitignore +161 -0
- gofeatureflag_python_provider-1.0.0/AGENTS.md +148 -0
- gofeatureflag_python_provider-1.0.0/CHANGELOG.md +50 -0
- gofeatureflag_python_provider-1.0.0/CLAUDE.md +1 -0
- {gofeatureflag_python_provider-0.4.4 → gofeatureflag_python_provider-1.0.0}/PKG-INFO +16 -28
- {gofeatureflag_python_provider-0.4.4 → gofeatureflag_python_provider-1.0.0}/README.md +3 -4
- gofeatureflag_python_provider-1.0.0/clean.py +0 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/__init__.py +1 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/evaluator/__init__.py +17 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/evaluator/abstract_evaluator.py +136 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/evaluator/inprocess_evaluator.py +330 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/evaluator/remote_evaluator.py +189 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/exceptions.py +25 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/hooks/__init__.py +6 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/hooks/data_collector.py +83 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/hooks/enrich_evaluation_context.py +27 -0
- {gofeatureflag_python_provider-0.4.4 → gofeatureflag_python_provider-1.0.0}/gofeatureflag_python_provider/options.py +41 -3
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/provider.py +312 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/services/__init__.py +25 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/services/api.py +210 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/services/event_publisher.py +157 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/services/models.py +23 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/wasm/__init__.py +15 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/wasm/_wasi_version.txt +1 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/wasm/evaluate_wasm.py +203 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/wasm/gofeatureflag-evaluation_0.2.0.wasi +0 -0
- gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/wasm/models.py +40 -0
- gofeatureflag_python_provider-1.0.0/hatch_build.py +0 -0
- gofeatureflag_python_provider-1.0.0/pyproject.toml +56 -0
- gofeatureflag_python_provider-1.0.0/tests/.gitignore +1 -0
- gofeatureflag_python_provider-1.0.0/tests/__init__.py +0 -0
- gofeatureflag_python_provider-1.0.0/tests/config.goff.yaml +176 -0
- gofeatureflag_python_provider-1.0.0/tests/conftest.py +0 -0
- gofeatureflag_python_provider-1.0.0/tests/docker-compose.yml +15 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/config/valid-all-types-config-change.json +248 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/config/valid-all-types.json +248 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/config/valid-flag-config.json +25 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/config/valid-scheduled-rollout.json +58 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/bool_targeting_match.json +11 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/bool_targeting_match_no_error_field.json +11 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/disabled_bool.json +6 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/disabled_float.json +6 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/disabled_int.json +6 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/disabled_object.json +8 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/disabled_string.json +6 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/double_key.json +6 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/flag_not_found.json +5 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/integer_key.json +6 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/invalid_json_body.json +7 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/list_key.json +12 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/object_key.json +12 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/string_key.json +6 -0
- gofeatureflag_python_provider-1.0.0/tests/mock_responses/ofrep/unknown_reason.json +5 -0
- gofeatureflag_python_provider-1.0.0/tests/test_data_collector_hook.py +287 -0
- gofeatureflag_python_provider-1.0.0/tests/test_enrich_evaluation_context_hook.py +82 -0
- gofeatureflag_python_provider-1.0.0/tests/test_evaluate_wasm.py +348 -0
- gofeatureflag_python_provider-1.0.0/tests/test_event_publisher.py +156 -0
- gofeatureflag_python_provider-1.0.0/tests/test_gofeatureflag_provider.py +839 -0
- gofeatureflag_python_provider-1.0.0/tests/test_gofeatureflag_provider_inprocess.py +333 -0
- gofeatureflag_python_provider-1.0.0/tests/test_inprocess_evaluator.py +569 -0
- gofeatureflag_python_provider-1.0.0/tests/test_provider_graceful_exit.py +90 -0
- gofeatureflag_python_provider-1.0.0/tests/test_remote_evaluator_ofrep.py +86 -0
- gofeatureflag_python_provider-1.0.0/tests/test_services_api.py +586 -0
- gofeatureflag_python_provider-1.0.0/tests/test_websocket_cache_invalidation.py +121 -0
- gofeatureflag_python_provider-1.0.0/uv.lock +860 -0
- gofeatureflag_python_provider-0.4.4/gofeatureflag_python_provider/__init__.py +0 -1
- gofeatureflag_python_provider-0.4.4/gofeatureflag_python_provider/data_collector_hook.py +0 -142
- gofeatureflag_python_provider-0.4.4/gofeatureflag_python_provider/provider.py +0 -326
- gofeatureflag_python_provider-0.4.4/pyproject.toml +0 -47
- {gofeatureflag_python_provider-0.4.4 → gofeatureflag_python_provider-1.0.0}/gofeatureflag_python_provider/metadata.py +0 -0
- {gofeatureflag_python_provider-0.4.4 → gofeatureflag_python_provider-1.0.0}/gofeatureflag_python_provider/request_data_collector.py +0 -0
- {gofeatureflag_python_provider-0.4.4 → gofeatureflag_python_provider-1.0.0}/gofeatureflag_python_provider/request_flag_evaluation.py +0 -0
- {gofeatureflag_python_provider-0.4.4 → gofeatureflag_python_provider-1.0.0}/gofeatureflag_python_provider/response_flag_evaluation.py +0 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# uv
|
|
98
|
+
# uv.lock is recommended to be included in version control for reproducibility.
|
|
99
|
+
# https://docs.astral.sh/uv/concepts/projects/layout/#the-lockfile
|
|
100
|
+
#uv.lock
|
|
101
|
+
|
|
102
|
+
# pdm
|
|
103
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
104
|
+
#pdm.lock
|
|
105
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
106
|
+
# in version control.
|
|
107
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
108
|
+
.pdm.toml
|
|
109
|
+
|
|
110
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
111
|
+
__pypackages__/
|
|
112
|
+
|
|
113
|
+
# Celery stuff
|
|
114
|
+
celerybeat-schedule
|
|
115
|
+
celerybeat.pid
|
|
116
|
+
|
|
117
|
+
# SageMath parsed files
|
|
118
|
+
*.sage.py
|
|
119
|
+
|
|
120
|
+
# Environments
|
|
121
|
+
.env
|
|
122
|
+
.venv
|
|
123
|
+
env/
|
|
124
|
+
venv/
|
|
125
|
+
ENV/
|
|
126
|
+
env.bak/
|
|
127
|
+
venv.bak/
|
|
128
|
+
|
|
129
|
+
# Spyder project settings
|
|
130
|
+
.spyderproject
|
|
131
|
+
.spyproject
|
|
132
|
+
|
|
133
|
+
# Rope project settings
|
|
134
|
+
.ropeproject
|
|
135
|
+
|
|
136
|
+
# mkdocs documentation
|
|
137
|
+
/site
|
|
138
|
+
|
|
139
|
+
# mypy
|
|
140
|
+
.mypy_cache/
|
|
141
|
+
.dmypy.json
|
|
142
|
+
dmypy.json
|
|
143
|
+
|
|
144
|
+
# Pyre type checker
|
|
145
|
+
.pyre/
|
|
146
|
+
|
|
147
|
+
# pytype static type analyzer
|
|
148
|
+
.pytype/
|
|
149
|
+
|
|
150
|
+
# Cython debug symbols
|
|
151
|
+
cython_debug/
|
|
152
|
+
|
|
153
|
+
# PyCharm
|
|
154
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
155
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
156
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
157
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
158
|
+
.idea/
|
|
159
|
+
|
|
160
|
+
./gofeatureflag_python_provider/wasm/_wasi_version.txt
|
|
161
|
+
./gofeatureflag_python_provider/wasm/gofeatureflag-evaluation_*.wasi
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# GO Feature Flag Python Provider
|
|
2
|
+
|
|
3
|
+
OpenFeature Python provider for [GO Feature Flag](https://gofeatureflag.org).
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
This is a Python package that implements the OpenFeature provider interface to connect to a GO Feature Flag relay proxy. It enables Python applications to evaluate feature flags using the OpenFeature SDK.
|
|
8
|
+
|
|
9
|
+
## Architecture
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
gofeatureflag_python_provider/
|
|
13
|
+
├── __init__.py # Package exports
|
|
14
|
+
├── provider.py # Main GoFeatureFlagProvider class (AbstractProvider implementation)
|
|
15
|
+
├── options.py # GoFeatureFlagOptions configuration class
|
|
16
|
+
├── hooks/ # OpenFeature hooks
|
|
17
|
+
│ ├── __init__.py
|
|
18
|
+
│ ├── data_collector.py # Hook for collecting flag evaluation usage data
|
|
19
|
+
│ └── enrich_evaluation_context.py # Hook that adds gofeatureflag metadata to context before evaluation
|
|
20
|
+
├── metadata.py # Provider metadata
|
|
21
|
+
├── request_data_collector.py # Data models for usage collection
|
|
22
|
+
├── request_flag_evaluation.py # Request models for flag evaluation API calls
|
|
23
|
+
└── response_flag_evaluation.py # Response models for flag evaluation API calls
|
|
24
|
+
|
|
25
|
+
tests/
|
|
26
|
+
├── test_gofeatureflag_python_provider.py # Main provider tests
|
|
27
|
+
├── test_enrich_evaluation_context_hook.py # EnrichEvaluationContextHook tests
|
|
28
|
+
├── test_provider_graceful_exit.py # Shutdown/cleanup tests
|
|
29
|
+
├── test_websocket_cache_invalidation.py # WebSocket cache invalidation tests
|
|
30
|
+
├── mock_responses/ # JSON mock responses for testing
|
|
31
|
+
├── config.goff.yaml # Test flag configuration
|
|
32
|
+
└── docker-compose.yml # Test infrastructure
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Key Components
|
|
36
|
+
|
|
37
|
+
### GoFeatureFlagProvider (`provider.py`)
|
|
38
|
+
- Extends `AbstractProvider` from OpenFeature SDK
|
|
39
|
+
- Implements all resolve methods: `resolve_boolean_details`, `resolve_string_details`, `resolve_integer_details`, `resolve_float_details`, `resolve_object_details`
|
|
40
|
+
- Uses `generic_go_feature_flag_resolver` for all flag types
|
|
41
|
+
- Features:
|
|
42
|
+
- LRU cache for flag evaluations (`pylru`)
|
|
43
|
+
- WebSocket connection for cache invalidation
|
|
44
|
+
- Data collection for usage analytics
|
|
45
|
+
|
|
46
|
+
### GoFeatureFlagOptions (`options.py`)
|
|
47
|
+
Configuration options:
|
|
48
|
+
- `endpoint` (required): URL of the GO Feature Flag relay proxy
|
|
49
|
+
- `cache_size`: Max cached flags (default: 10000)
|
|
50
|
+
- `data_flush_interval`: Interval to flush usage data in ms (default: 60000)
|
|
51
|
+
- `disable_data_collection`: Turn off usage tracking (default: false)
|
|
52
|
+
- `reconnect_interval`: WebSocket reconnect interval in seconds (default: 60)
|
|
53
|
+
- `disable_cache_invalidation`: Disable WebSocket cache invalidation (default: false)
|
|
54
|
+
- `api_key`: API key for authenticated requests
|
|
55
|
+
- `exporter_metadata`: Custom metadata for evaluation events
|
|
56
|
+
- `debug`: Enable debug logging (default: false)
|
|
57
|
+
- `urllib3_pool_manager`: Custom HTTP client
|
|
58
|
+
|
|
59
|
+
### DataCollectorHook (`hooks/data_collector.py`)
|
|
60
|
+
- OpenFeature Hook implementation for collecting usage data
|
|
61
|
+
- Tracks flag evaluations via `after()` and `error()` hooks
|
|
62
|
+
- Flushes data to `/v1/data/collector` endpoint periodically
|
|
63
|
+
|
|
64
|
+
### EnrichEvaluationContextHook (`hooks/enrich_evaluation_context.py`)
|
|
65
|
+
- Enriches the evaluation context with a `gofeatureflag` attribute (from `exporter_metadata`) before flag resolution
|
|
66
|
+
- Used by the relay proxy for analytics or filtering; registered automatically by the provider
|
|
67
|
+
|
|
68
|
+
## Development
|
|
69
|
+
|
|
70
|
+
### Prerequisites
|
|
71
|
+
- Python 3.9+
|
|
72
|
+
- uv (package manager)
|
|
73
|
+
|
|
74
|
+
### Setup
|
|
75
|
+
```bash
|
|
76
|
+
# Install dependencies
|
|
77
|
+
uv sync
|
|
78
|
+
|
|
79
|
+
# Run a command in the virtual environment
|
|
80
|
+
uv run <command>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Running Tests
|
|
84
|
+
```bash
|
|
85
|
+
# Run all tests
|
|
86
|
+
uv run pytest
|
|
87
|
+
|
|
88
|
+
# Run specific test file
|
|
89
|
+
uv run pytest tests/test_gofeatureflag_python_provider.py
|
|
90
|
+
|
|
91
|
+
# Run with verbose output
|
|
92
|
+
uv run pytest -v
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Code Style
|
|
96
|
+
```bash
|
|
97
|
+
# Format code with black
|
|
98
|
+
uv run black gofeatureflag_python_provider tests
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Key Patterns
|
|
102
|
+
|
|
103
|
+
### Pydantic Models
|
|
104
|
+
- All data classes extend Pydantic `BaseModel` for validation
|
|
105
|
+
- Request/response models use `model_dump_json()` for serialization
|
|
106
|
+
- Use `model_validate_json()` for deserialization
|
|
107
|
+
|
|
108
|
+
### HTTP Communication
|
|
109
|
+
- Uses `urllib3.PoolManager` for HTTP requests
|
|
110
|
+
- POST to `/v1/feature/{flag_key}/eval` for flag evaluation
|
|
111
|
+
- POST to `/v1/data/collector` for usage data
|
|
112
|
+
- WebSocket at `/ws/v1/flag/change` for cache invalidation
|
|
113
|
+
|
|
114
|
+
### Caching Strategy
|
|
115
|
+
- LRU cache keyed by `{flag_key}:{evaluation_context_hash()}`
|
|
116
|
+
- Cache cleared on WebSocket message (flag config changed)
|
|
117
|
+
- Set `cacheable` field in response determines if result is cached
|
|
118
|
+
|
|
119
|
+
### Error Handling
|
|
120
|
+
- `FlagNotFoundError`: Flag doesn't exist (404)
|
|
121
|
+
- `InvalidContextError`: Invalid evaluation context (400)
|
|
122
|
+
- `TypeMismatchError`: Response type doesn't match expected type
|
|
123
|
+
- `GeneralError`: Other errors (500+)
|
|
124
|
+
|
|
125
|
+
## API Reference
|
|
126
|
+
|
|
127
|
+
The provider communicates with the GO Feature Flag relay proxy:
|
|
128
|
+
|
|
129
|
+
| Endpoint | Method | Purpose |
|
|
130
|
+
|----------|--------|---------|
|
|
131
|
+
| `/v1/feature/{flag}/eval` | POST | Evaluate a flag |
|
|
132
|
+
| `/v1/data/collector` | POST | Send usage data |
|
|
133
|
+
| `/ws/v1/flag/change` | WebSocket | Cache invalidation notifications |
|
|
134
|
+
|
|
135
|
+
## Dependencies
|
|
136
|
+
|
|
137
|
+
Core:
|
|
138
|
+
- `openfeature-sdk`: OpenFeature Python SDK
|
|
139
|
+
- `pydantic`: Data validation
|
|
140
|
+
- `urllib3`: HTTP client
|
|
141
|
+
- `pylru`: LRU cache implementation
|
|
142
|
+
- `websocket-client`: WebSocket support
|
|
143
|
+
- `rel`: WebSocket reconnection handling
|
|
144
|
+
|
|
145
|
+
Dev:
|
|
146
|
+
- `pytest`: Testing framework
|
|
147
|
+
- `black`: Code formatter
|
|
148
|
+
- `pytest-docker`: Docker-based integration tests
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [1.0.0](https://github.com/thomaspoignant/go-feature-flag/compare/openfeature/providers/python-provider/v0.5.0...openfeature/providers/python-provider/v1.0.0) (2026-03-31)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* **python:** New python provider with inprocess support ([#4861](https://github.com/thomaspoignant/go-feature-flag/issues/4861))
|
|
9
|
+
|
|
10
|
+
### 🚀 New Features
|
|
11
|
+
|
|
12
|
+
* **python:** New python provider with inprocess support ([#4861](https://github.com/thomaspoignant/go-feature-flag/issues/4861)) ([d67c24b](https://github.com/thomaspoignant/go-feature-flag/commit/d67c24b3f5969a7d3ec5a2cd893d6094e3534152))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### 🔧 Chores
|
|
16
|
+
|
|
17
|
+
* Bump github.com/aws/aws-sdk-go-v2/service/s3 ([#4613](https://github.com/thomaspoignant/go-feature-flag/issues/4613)) ([a8e9b13](https://github.com/thomaspoignant/go-feature-flag/commit/a8e9b136eb972da636726525bffc1c2f86fcb432))
|
|
18
|
+
* Bump go.opentelemetry.io/otel/sdk from 1.41.0 to 1.42.0 ([#4944](https://github.com/thomaspoignant/go-feature-flag/issues/4944)) ([ede0c19](https://github.com/thomaspoignant/go-feature-flag/commit/ede0c19d7452e55e9b8e27d1c929da9c0492a82a))
|
|
19
|
+
* Bump rel in /openfeature/providers/python-provider ([#4816](https://github.com/thomaspoignant/go-feature-flag/issues/4816)) ([abed2fc](https://github.com/thomaspoignant/go-feature-flag/commit/abed2fc066214042bf6002b988de6c32b7288873))
|
|
20
|
+
* Bump urllib3 in /openfeature/providers/python-provider ([#4605](https://github.com/thomaspoignant/go-feature-flag/issues/4605)) ([3d97b25](https://github.com/thomaspoignant/go-feature-flag/commit/3d97b256978c7f74f7e1a3eec229f6db553892ec))
|
|
21
|
+
|
|
22
|
+
## [0.5.0](https://github.com/thomaspoignant/go-feature-flag/compare/openfeature/providers/python-provider/v0.5.0...openfeature/providers/python-provider/v0.5.0) (2025-10-26)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### 🚀 New Features
|
|
26
|
+
|
|
27
|
+
* Python Provider Graceful Exit ([#4106](https://github.com/thomaspoignant/go-feature-flag/issues/4106)) ([b48cc0c](https://github.com/thomaspoignant/go-feature-flag/commit/b48cc0c0d3874e002eea174192251e0564540512))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### 🔧 Chores
|
|
31
|
+
|
|
32
|
+
* Bump pydantic in /openfeature/providers/python-provider ([#4050](https://github.com/thomaspoignant/go-feature-flag/issues/4050)) ([d4ea37f](https://github.com/thomaspoignant/go-feature-flag/commit/d4ea37fa7d3d91742acd75e246563699bb71b287))
|
|
33
|
+
* Bump pydantic in /openfeature/providers/python-provider ([#4120](https://github.com/thomaspoignant/go-feature-flag/issues/4120)) ([beda91c](https://github.com/thomaspoignant/go-feature-flag/commit/beda91cbbc0369c38c71178b92ab13f1103e83a6))
|
|
34
|
+
* Bump websocket-client in /openfeature/providers/python-provider ([#4053](https://github.com/thomaspoignant/go-feature-flag/issues/4053)) ([4147232](https://github.com/thomaspoignant/go-feature-flag/commit/4147232126e8f6af5a03a90001d07177ba1e60a8))
|
|
35
|
+
* **main:** release openfeature/providers/python-provider 0.5.0 ([#4065](https://github.com/thomaspoignant/go-feature-flag/issues/4065)) ([fb0d9ba](https://github.com/thomaspoignant/go-feature-flag/commit/fb0d9babaeae8fc4721c6bcd9a566d8c6e5502a9))
|
|
36
|
+
* Release python as v0.5.0 ([#4142](https://github.com/thomaspoignant/go-feature-flag/issues/4142)) ([0c1508a](https://github.com/thomaspoignant/go-feature-flag/commit/0c1508a7bc466be35d18f3026668f0896f8fa55e))
|
|
37
|
+
|
|
38
|
+
## [0.5.0](https://github.com/thomaspoignant/go-feature-flag/compare/openfeature/providers/python-provider/v0.4.4...openfeature/providers/python-provider/v0.5.0) (2025-10-26)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
### 🚀 New Features
|
|
42
|
+
|
|
43
|
+
* Python Provider Graceful Exit ([#4106](https://github.com/thomaspoignant/go-feature-flag/issues/4106)) ([b48cc0c](https://github.com/thomaspoignant/go-feature-flag/commit/b48cc0c0d3874e002eea174192251e0564540512))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
### 🔧 Chores
|
|
47
|
+
|
|
48
|
+
* Bump pydantic in /openfeature/providers/python-provider ([#4050](https://github.com/thomaspoignant/go-feature-flag/issues/4050)) ([d4ea37f](https://github.com/thomaspoignant/go-feature-flag/commit/d4ea37fa7d3d91742acd75e246563699bb71b287))
|
|
49
|
+
* Bump pydantic in /openfeature/providers/python-provider ([#4120](https://github.com/thomaspoignant/go-feature-flag/issues/4120)) ([beda91c](https://github.com/thomaspoignant/go-feature-flag/commit/beda91cbbc0369c38c71178b92ab13f1103e83a6))
|
|
50
|
+
* Bump websocket-client in /openfeature/providers/python-provider ([#4053](https://github.com/thomaspoignant/go-feature-flag/issues/4053)) ([4147232](https://github.com/thomaspoignant/go-feature-flag/commit/4147232126e8f6af5a03a90001d07177ba1e60a8))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
@@ -1,36 +1,26 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: gofeatureflag-python-provider
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: GO Feature Flag provider for OpenFeature
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
Project-URL: Bug Tracker, https://github.com/thomaspoignant/go-feature-flag/issues
|
|
6
|
+
Project-URL: Source Code, https://github.com/thomaspoignant/go-feature-flag/tree/main/openfeature/providers/python-provider
|
|
7
|
+
Project-URL: Documentation, https://github.com/thomaspoignant/go-feature-flag/tree/main/openfeature/providers/python-provider
|
|
7
8
|
Author: Thomas Poignant
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
Keywords: feature flags,feature toggles,go-feature-flag,gofeatureflag,open-feature,openfeature
|
|
16
11
|
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
17
12
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
-
Requires-
|
|
19
|
-
Requires-Dist:
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist:
|
|
22
|
-
Requires-Dist: urllib3
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Project-URL: Bug Tracker, https://github.com/thomaspoignant/go-feature-flag/issues
|
|
25
|
-
Project-URL: Documentation, https://github.com/thomaspoignant/go-feature-flag/tree/main/openfeature/providers/python-provider
|
|
26
|
-
Project-URL: Homepage, https://gofeatureflag.org
|
|
27
|
-
Project-URL: Repository, https://github.com/thomaspoignant/go-feature-flag
|
|
28
|
-
Project-URL: Source Code, https://github.com/thomaspoignant/go-feature-flag/tree/main/openfeature/providers/python-provider
|
|
13
|
+
Requires-Python: >=3.9
|
|
14
|
+
Requires-Dist: openfeature-provider-ofrep>=0.2.0
|
|
15
|
+
Requires-Dist: openfeature-sdk<0.9.0,>=0.8.4
|
|
16
|
+
Requires-Dist: pydantic>=2.5.2
|
|
17
|
+
Requires-Dist: urllib3>=2.1.0
|
|
18
|
+
Requires-Dist: wasmtime>=41.0.0
|
|
29
19
|
Description-Content-Type: text/markdown
|
|
30
20
|
|
|
31
21
|
# GO Feature Flag Python Provider
|
|
32
22
|
|
|
33
|
-
GO Feature Flag provider allows you to connect to your GO Feature Flag instance.
|
|
23
|
+
GO Feature Flag provider allows you to connect to your GO Feature Flag instance.
|
|
34
24
|
|
|
35
25
|
[GO Feature Flag](https://gofeatureflag.org) believes in simplicity and offers a simple and lightweight solution to use feature flags.
|
|
36
26
|
Our focus is to avoid any complex infrastructure work to use GO Feature Flag.
|
|
@@ -71,9 +61,8 @@ client = api.get_client(domain="test-client")
|
|
|
71
61
|
|
|
72
62
|
This code block explains how you can create an `EvaluationContext` and use it to evaluate your flag.
|
|
73
63
|
|
|
74
|
-
|
|
75
64
|
> In this example we are evaluating a `boolean` flag, but other types are available.
|
|
76
|
-
>
|
|
65
|
+
>
|
|
77
66
|
> **Refer to the [Open Feature documentation](https://docs.openfeature.dev/docs/reference/concepts/evaluation-api#basic-evaluation) to know more about it.**
|
|
78
67
|
|
|
79
68
|
```python
|
|
@@ -99,10 +88,9 @@ admin_flag = client.get_boolean_value(
|
|
|
99
88
|
default_value=default_value,
|
|
100
89
|
evaluation_context=ctx,
|
|
101
90
|
)
|
|
102
|
-
|
|
91
|
+
|
|
103
92
|
if admin_flag:
|
|
104
93
|
# flag "flag-only-for-admin" is true for the user
|
|
105
94
|
else:
|
|
106
95
|
# flag "flag-only-for-admin" is false for the user
|
|
107
96
|
```
|
|
108
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# GO Feature Flag Python Provider
|
|
2
2
|
|
|
3
|
-
GO Feature Flag provider allows you to connect to your GO Feature Flag instance.
|
|
3
|
+
GO Feature Flag provider allows you to connect to your GO Feature Flag instance.
|
|
4
4
|
|
|
5
5
|
[GO Feature Flag](https://gofeatureflag.org) believes in simplicity and offers a simple and lightweight solution to use feature flags.
|
|
6
6
|
Our focus is to avoid any complex infrastructure work to use GO Feature Flag.
|
|
@@ -41,9 +41,8 @@ client = api.get_client(domain="test-client")
|
|
|
41
41
|
|
|
42
42
|
This code block explains how you can create an `EvaluationContext` and use it to evaluate your flag.
|
|
43
43
|
|
|
44
|
-
|
|
45
44
|
> In this example we are evaluating a `boolean` flag, but other types are available.
|
|
46
|
-
>
|
|
45
|
+
>
|
|
47
46
|
> **Refer to the [Open Feature documentation](https://docs.openfeature.dev/docs/reference/concepts/evaluation-api#basic-evaluation) to know more about it.**
|
|
48
47
|
|
|
49
48
|
```python
|
|
@@ -69,7 +68,7 @@ admin_flag = client.get_boolean_value(
|
|
|
69
68
|
default_value=default_value,
|
|
70
69
|
evaluation_context=ctx,
|
|
71
70
|
)
|
|
72
|
-
|
|
71
|
+
|
|
73
72
|
if admin_flag:
|
|
74
73
|
# flag "flag-only-for-admin" is true for the user
|
|
75
74
|
else:
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.0"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Evaluator implementations for GO Feature Flag provider.
|
|
3
|
+
|
|
4
|
+
Selects remote (relay proxy) or inprocess (local/WASM) evaluation based on options.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from gofeatureflag_python_provider.evaluator.abstract_evaluator import AbstractEvaluator
|
|
8
|
+
from gofeatureflag_python_provider.evaluator.inprocess_evaluator import (
|
|
9
|
+
InProcessEvaluator,
|
|
10
|
+
)
|
|
11
|
+
from gofeatureflag_python_provider.evaluator.remote_evaluator import RemoteEvaluator
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"AbstractEvaluator",
|
|
15
|
+
"InProcessEvaluator",
|
|
16
|
+
"RemoteEvaluator",
|
|
17
|
+
]
|
gofeatureflag_python_provider-1.0.0/gofeatureflag_python_provider/evaluator/abstract_evaluator.py
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Abstract interface for flag evaluation.
|
|
3
|
+
|
|
4
|
+
Implementations: RemoteEvaluator (relay proxy), InProcessEvaluator (local/WASM).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from abc import ABC, abstractmethod
|
|
8
|
+
from typing import Optional, Union
|
|
9
|
+
|
|
10
|
+
from openfeature.evaluation_context import EvaluationContext
|
|
11
|
+
from openfeature.flag_evaluation import FlagResolutionDetails
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AbstractEvaluator(ABC):
|
|
15
|
+
"""Interface for evaluating feature flags (remote or in-process)."""
|
|
16
|
+
|
|
17
|
+
@abstractmethod
|
|
18
|
+
def initialize(
|
|
19
|
+
self, evaluation_context: Optional[EvaluationContext] = None
|
|
20
|
+
) -> None:
|
|
21
|
+
"""Initialize the evaluator (e.g. cache, WebSocket, WASM)."""
|
|
22
|
+
...
|
|
23
|
+
|
|
24
|
+
@abstractmethod
|
|
25
|
+
def shutdown(self) -> None:
|
|
26
|
+
"""Release resources (connections, threads, etc.)."""
|
|
27
|
+
...
|
|
28
|
+
|
|
29
|
+
# --- Sync evaluation ---
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def resolve_boolean_details(
|
|
33
|
+
self,
|
|
34
|
+
flag_key: str,
|
|
35
|
+
default_value: bool,
|
|
36
|
+
evaluation_context: Optional[EvaluationContext] = None,
|
|
37
|
+
) -> FlagResolutionDetails[bool]:
|
|
38
|
+
"""Resolve the flag as a boolean."""
|
|
39
|
+
...
|
|
40
|
+
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def resolve_string_details(
|
|
43
|
+
self,
|
|
44
|
+
flag_key: str,
|
|
45
|
+
default_value: str,
|
|
46
|
+
evaluation_context: Optional[EvaluationContext] = None,
|
|
47
|
+
) -> FlagResolutionDetails[str]:
|
|
48
|
+
"""Resolve the flag as a string."""
|
|
49
|
+
...
|
|
50
|
+
|
|
51
|
+
@abstractmethod
|
|
52
|
+
def resolve_integer_details(
|
|
53
|
+
self,
|
|
54
|
+
flag_key: str,
|
|
55
|
+
default_value: int,
|
|
56
|
+
evaluation_context: Optional[EvaluationContext] = None,
|
|
57
|
+
) -> FlagResolutionDetails[int]:
|
|
58
|
+
"""Resolve the flag as an integer."""
|
|
59
|
+
...
|
|
60
|
+
|
|
61
|
+
@abstractmethod
|
|
62
|
+
def resolve_float_details(
|
|
63
|
+
self,
|
|
64
|
+
flag_key: str,
|
|
65
|
+
default_value: float,
|
|
66
|
+
evaluation_context: Optional[EvaluationContext] = None,
|
|
67
|
+
) -> FlagResolutionDetails[float]:
|
|
68
|
+
"""Resolve the flag as a float."""
|
|
69
|
+
...
|
|
70
|
+
|
|
71
|
+
@abstractmethod
|
|
72
|
+
def resolve_object_details(
|
|
73
|
+
self,
|
|
74
|
+
flag_key: str,
|
|
75
|
+
default_value: Union[dict, list],
|
|
76
|
+
evaluation_context: Optional[EvaluationContext] = None,
|
|
77
|
+
) -> FlagResolutionDetails[Union[list, dict]]:
|
|
78
|
+
"""Resolve the flag as an object."""
|
|
79
|
+
...
|
|
80
|
+
|
|
81
|
+
# --- Async evaluation ---
|
|
82
|
+
|
|
83
|
+
@abstractmethod
|
|
84
|
+
async def resolve_boolean_details_async(
|
|
85
|
+
self,
|
|
86
|
+
flag_key: str,
|
|
87
|
+
default_value: bool,
|
|
88
|
+
evaluation_context: Optional[EvaluationContext] = None,
|
|
89
|
+
) -> FlagResolutionDetails[bool]:
|
|
90
|
+
"""Asynchronously resolve the flag as a boolean."""
|
|
91
|
+
...
|
|
92
|
+
|
|
93
|
+
@abstractmethod
|
|
94
|
+
async def resolve_string_details_async(
|
|
95
|
+
self,
|
|
96
|
+
flag_key: str,
|
|
97
|
+
default_value: str,
|
|
98
|
+
evaluation_context: Optional[EvaluationContext] = None,
|
|
99
|
+
) -> FlagResolutionDetails[str]:
|
|
100
|
+
"""Asynchronously resolve the flag as a string."""
|
|
101
|
+
...
|
|
102
|
+
|
|
103
|
+
@abstractmethod
|
|
104
|
+
async def resolve_integer_details_async(
|
|
105
|
+
self,
|
|
106
|
+
flag_key: str,
|
|
107
|
+
default_value: int,
|
|
108
|
+
evaluation_context: Optional[EvaluationContext] = None,
|
|
109
|
+
) -> FlagResolutionDetails[int]:
|
|
110
|
+
"""Asynchronously resolve the flag as an integer."""
|
|
111
|
+
...
|
|
112
|
+
|
|
113
|
+
@abstractmethod
|
|
114
|
+
async def resolve_float_details_async(
|
|
115
|
+
self,
|
|
116
|
+
flag_key: str,
|
|
117
|
+
default_value: float,
|
|
118
|
+
evaluation_context: Optional[EvaluationContext] = None,
|
|
119
|
+
) -> FlagResolutionDetails[float]:
|
|
120
|
+
"""Asynchronously resolve the flag as a float."""
|
|
121
|
+
...
|
|
122
|
+
|
|
123
|
+
@abstractmethod
|
|
124
|
+
async def resolve_object_details_async(
|
|
125
|
+
self,
|
|
126
|
+
flag_key: str,
|
|
127
|
+
default_value: Union[dict, list],
|
|
128
|
+
evaluation_context: Optional[EvaluationContext] = None,
|
|
129
|
+
) -> FlagResolutionDetails[Union[dict, list]]:
|
|
130
|
+
"""Asynchronously resolve the flag as an object."""
|
|
131
|
+
...
|
|
132
|
+
|
|
133
|
+
@abstractmethod
|
|
134
|
+
def is_flag_trackable(self, flag_key: str) -> bool:
|
|
135
|
+
"""Check if the flag is trackable."""
|
|
136
|
+
...
|