+
+
+[OpenFeature](https://openfeature.dev) is an open specification that provides a vendor-agnostic, community-driven API for feature flagging that works with your favorite feature flag management tool.
+
+
+
+## 🚀 Quick start
+
+### Requirements
+
+- Python 3.8+
+
+### Install
+
+
+
+#### Pip install
+
+```bash
+pip install openfeature-sdk==0.3.1
+```
+
+#### requirements.txt
+
+```bash
+openfeature-sdk==0.3.1
+```
+
+```python
+pip install -r requirements.txt
+```
+
+
+
+### Usage
+
+```python
+from openfeature import api
+from openfeature.provider.in_memory_provider import InMemoryFlag, InMemoryProvider
+
+# flags defined in memory
+my_flags = {
+ "v2_enabled": InMemoryFlag("on", {"on": True, "off": False})
+}
+
+# configure a provider
+api.set_provider(InMemoryProvider(my_flags))
+
+# create a client
+client = api.get_client()
+
+# get a bool flag value
+flag_value = client.get_boolean_value("v2_enabled", False)
+print("Value: " + str(flag_value))
+```
+
+## 🌟 Features
+
+| Status | Features | Description |
+| ------ | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
+| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. |
+| ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). |
+| ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. |
+| ❌ | [Logging](#logging) | Integrate with popular logging packages. |
+| ❌ | [Named clients](#named-clients) | Utilize multiple providers in a single application. |
+| ❌ | [Eventing](#eventing) | React to state changes in the provider or flag management system. |
+| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
+| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
+
+Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌
+
+### Providers
+
+[Providers](https://openfeature.dev/docs/reference/concepts/provider) are an abstraction between a flag management system and the OpenFeature SDK.
+Look [here](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Provider&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=python) for a complete list of available providers.
+If the provider you're looking for hasn't been created yet, see the [develop a provider](#develop-a-provider) section to learn how to build it yourself.
+
+Once you've added a provider as a dependency, it can be registered with OpenFeature like this:
+
+```python
+from openfeature import api
+from openfeature.provider.no_op_provider import NoOpProvider
+
+api.set_provider(NoOpProvider())
+open_feature_client = api.get_client()
+```
+
+
+
+### Targeting
+
+Sometimes, the value of a flag must consider some dynamic criteria about the application or user, such as the user's location, IP, email address, or the server's location.
+In OpenFeature, we refer to this as [targeting](https://openfeature.dev/specification/glossary#targeting).
+If the flag management system you're using supports targeting, you can provide the input data using the [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context).
+
+```python
+from openfeature.api import (
+ get_client,
+ get_provider,
+ set_provider,
+ get_evaluation_context,
+ set_evaluation_context,
+)
+
+global_context = EvaluationContext(
+ targeting_key="targeting_key1", attributes={"application": "value1"}
+)
+request_context = EvaluationContext(
+ targeting_key="targeting_key2", attributes={"email": request.form['email']}
+)
+
+## set global context
+set_evaluation_context(global_context)
+
+# merge second context
+client = get_client(name="No-op Provider")
+client.get_string_value("email", "fallback", request_context)
+```
+
+### Hooks
+
+[Hooks](https://openfeature.dev/docs/reference/concepts/hooks) allow for custom logic to be added at well-defined points of the flag evaluation life-cycle.
+Look [here](https://openfeature.dev/ecosystem/?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Hook&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=python) for a complete list of available hooks.
+If the hook you're looking for hasn't been created yet, see the [develop a hook](#develop-a-hook) section to learn how to build it yourself.
+
+Once you've added a hook as a dependency, it can be registered at the global, client, or flag invocation level.
+
+```python
+from openfeature.api import add_hooks
+from openfeature.flag_evaluation import FlagEvaluationOptions
+
+# set global hooks at the API-level
+add_hooks([MyHook()])
+
+# or configure them in the client
+client = OpenFeatureClient()
+client.add_hooks([MyHook()])
+
+# or at the invocation-level
+options = FlagEvaluationOptions(hooks=[MyHook()])
+client.get_boolean_flag("my-flag", False, flag_evaluation_options=options)
+```
+
+### Logging
+
+Logging customization is not yet available in the Python SDK.
+
+### Named clients
+
+Named clients are not yet available in the Python SDK. Progress on this feature can be tracked [here](https://github.com/open-feature/python-sdk/issues/125).
+
+### Eventing
+
+Events are not yet available in the Python SDK. Progress on this feature can be tracked [here](https://github.com/open-feature/python-sdk/issues/125).
+
+### Shutdown
+
+A shutdown method is not yet available in the Python SDK. Progress on this feature can be tracked [here](https://github.com/open-feature/python-sdk/issues/125).
+
+## Extending
+
+### Develop a provider
+
+To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency.
+This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/python-sdk-contrib) available under the OpenFeature organization.
+You’ll then need to write the provider by implementing the `AbstractProvider` class exported by the OpenFeature SDK.
+
+```python
+from typing import List, Optional
+
+from openfeature.evaluation_context import EvaluationContext
+from openfeature.flag_evaluation import FlagResolutionDetails
+from openfeature.provider.provider import AbstractProvider
+
+class MyProvider(AbstractProvider):
+ def get_metadata(self) -> Metadata:
+ ...
+
+ def get_provider_hooks(self) -> List[Hook]:
+ return []
+
+ def resolve_boolean_details(
+ self,
+ flag_key: str,
+ default_value: bool,
+ evaluation_context: Optional[EvaluationContext] = None,
+ ) -> FlagResolutionDetails[bool]:
+ ...
+
+ def resolve_string_details(
+ self,
+ flag_key: str,
+ default_value: str,
+ evaluation_context: Optional[EvaluationContext] = None,
+ ) -> FlagResolutionDetails[str]:
+ ...
+
+ def resolve_integer_details(
+ self,
+ flag_key: str,
+ default_value: int,
+ evaluation_context: Optional[EvaluationContext] = None,
+ ) -> FlagResolutionDetails[int]:
+ ...
+
+ def resolve_float_details(
+ self,
+ flag_key: str,
+ default_value: float,
+ evaluation_context: Optional[EvaluationContext] = None,
+ ) -> FlagResolutionDetails[float]:
+ ...
+
+ def resolve_object_details(
+ self,
+ flag_key: str,
+ default_value: Union[dict, list],
+ evaluation_context: Optional[EvaluationContext] = None,
+ ) -> FlagResolutionDetails[Union[dict, list]]:
+ ...
+```
+
+> Built a new provider? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=&labels=provider&projects=&template=document-provider.yaml&title=%5BProvider%5D%3A+) so we can add it to the docs!
+
+### Develop a hook
+
+To develop a hook, you need to create a new project and include the OpenFeature SDK as a dependency.
+This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/python-sdk-contrib) available under the OpenFeature organization.
+Implement your own hook by creating a hook that inherits from the `Hook` class.
+Any of the evaluation life-cycle stages (`before`/`after`/`error`/`finally_after`) can be override to add the desired business logic.
+
+```python
+from openfeature.hook import Hook
+
+class MyHook(Hook):
+ def after(self, hook_context: HookContext, details: FlagEvaluationDetails, hints: dict):
+ print("This runs after the flag has been evaluated")
+
+```
+
+> Built a new hook? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=&labels=hook&projects=&template=document-hook.yaml&title=%5BHook%5D%3A+) so we can add it to the docs!
+
+
+
+## ⭐️ Support the project
+
+- Give this repo a ⭐️!
+- Follow us on social media:
+ - Twitter: [@openfeature](https://twitter.com/openfeature)
+ - LinkedIn: [OpenFeature](https://www.linkedin.com/company/openfeature/)
+- Join us on [Slack](https://cloud-native.slack.com/archives/C0344AANLA1)
+- For more, check out our [community page](https://openfeature.dev/community/)
+
+## 🤝 Contributing
+
+Interested in contributing? Great, we'd love your help! To get started, take a look at the [CONTRIBUTING](CONTRIBUTING.md) guide.
+
+### Thanks to everyone who has already contributed
+
+
+
+
+
+Made with [contrib.rocks](https://contrib.rocks).
+
+
diff --git a/readme.md b/readme.md
deleted file mode 100644
index 13564bd0..00000000
--- a/readme.md
+++ /dev/null
@@ -1,201 +0,0 @@
-
-
-
-
-
-
OpenFeature Python SDK
-
-[![PyPI version](https://badge.fury.io/py/openfeature-sdk.svg)](https://badge.fury.io/py/openfeature-sdk)
-![Python 3.8+](https://img.shields.io/badge/python->=3.8-blue.svg)
-[![Project Status: WIP – Initial development is in progress, but there has not yet been a stable, usable release suitable for the public.](https://www.repostatus.org/badges/latest/wip.svg)](https://www.repostatus.org/#wip)
-[![Specification](https://img.shields.io/static/v1?label=Specification&message=v0.3.0&color=red)](https://github.com/open-feature/spec/tree/v0.3.0)
-[![on-merge](https://github.com/open-feature/python-sdk/actions/workflows/merge.yml/badge.svg)](https://github.com/open-feature/python-sdk/actions/workflows/merge.yml)
-[![codecov](https://codecov.io/gh/open-feature/python-sdk/branch/main/graph/badge.svg?token=FQ1I444HB3)](https://codecov.io/gh/open-feature/python-sdk)
-
-> ⚠️ Development is in progress, but there's not a stable release available. ⚠️
-
-This is the Python implementation of [OpenFeature](https://openfeature.dev), a vendor-agnostic abstraction library for evaluating feature flags.
-
-We support multiple data types for flags (numbers, strings, booleans, objects) as well as hooks, which can alter the lifecycle of a flag evaluation.
-
-This library is intended to be used in server-side contexts and has not been evaluated for use in mobile devices.
-
-## 🔍 Requirements:
-
-- Python 3.8+
-
-## 📦 Installation:
-
-### Add it to your build
-
-
-
-Pip install
-
-```bash
-pip install openfeature-sdk==0.3.1
-```
-
-requirements.txt
-
-```bash
-openfeature-sdk==0.3.1
-```
-
-```python
-pip install requirements.txt
-```
-
-
-
-## 🌟 Features:
-
-- support for various backend [providers](https://openfeature.dev/docs/reference/concepts/provider)
-- easy integration and extension via [hooks](https://openfeature.dev/docs/reference/concepts/hooks)
-- bool, string, numeric, and object flag types
-- [context-aware](https://openfeature.dev/docs/reference/concepts/evaluation-context) evaluation
-
-## 🚀 Usage:
-
-### Configure it
-
-In order to use the sdk there is some minor configuration. Follow the script below:
-
-```python
-from openfeature import api
-from openfeature.provider.no_op_provider import NoOpProvider
-
-api.set_provider(NoOpProvider())
-open_feature_client = api.get_client()
-```
-
-### Basics:
-
-While Boolean provides the simplest introduction, we offer a variety of flag types.
-
-```python
-# Depending on the flag type, use one of the methods below
-flag_key = "PROVIDER_FLAG"
-boolean_result = open_feature_client.get_boolean_value(key=flag_key,default_value=False)
-integer_result = open_feature_client.get_integer_value(key=flag_key,default_value=-1)
-float_result = open_feature_client.get_float_value(key=flag_key,default_value=-1)
-string_result = open_feature_client.get_string_value(key=flag_key,default_value="")
-object_result = open_feature_client.get_object_value(key=flag_key,default_value={})
-```
-
-You can also bind a provider to a specific client by name instead of setting that provider globally:
-
-```python
-
-api.set_provider(NoOpProvider())
-```
-
-Each provider class may have further setup required i.e. secret keys, environment variables etc
-
-### Context-aware evaluation:
-
-Sometimes the value of a flag must take into account some dynamic criteria about the application or user, such as the user location, IP, email address, or the location of the server.
-In OpenFeature, we refer to this as [`targeting`](https://openfeature.dev/specification/glossary#targeting).
-If the flag system you're using supports targeting, you can provide the input data using the `EvaluationContext`.
-
-```python
-from openfeature.api import (
- get_client,
- get_provider,
- set_provider
- get_evaluation_context,
- set_evaluation_context,
-)
-
-global_context = EvaluationContext(
- targeting_key="targeting_key1", attributes={"application": "value1"}
-)
-request_context = EvaluationContext(
- targeting_key="targeting_key2", attributes={"email": request.form['email']}
-)
-
-## set global context
-set_evaluation_context(first_context)
-
-# merge second context
-client = get_client(name="No-op Provider", version="0.5.2")
-client.get_string_value("email", None, request_context)
-
-```
-
-### Events
-
-TBD (See Issue [#131](https://github.com/open-feature/python-sdk/issues/131))
-
-### Providers:
-
-To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency. This can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/python-sdk-contrib) available under the OpenFeature organization. Finally, you’ll then need to write the provider itself. This can be accomplished by implementing the `Provider` interface exported by the OpenFeature SDK.
-
-See [here](https://openfeature.dev/ecosystem) for a catalog of available providers.
-
-### Hooks:
-
-A hook is a mechanism that allows for adding arbitrary behavior at well-defined points of the flag evaluation life-cycle. Use cases include validating the resolved flag value, modifying or adding data to the evaluation context, logging, telemetry, and tracking.
-
-```python
-from openfeature.hook import Hook
-
-class MyHook(Hook):
- def after(self, hook_context: HookContext, details: FlagEvaluationDetails, hints: dict):
- print("This runs after the flag has been evaluated")
-
-
-# set global hooks at the API-level
-from openfeature.api import add_hooks
-add_hooks([MyHook()])
-
-# or configure them in the client
-client = OpenFeatureClient()
-client.add_hooks([MyHook()])
-```
-
-See [here](https://openfeature.dev/ecosystem) for a catalog of available hooks.
-
-### Logging:
-
-TBD
-
-## ⭐️ Support the project
-
-- Give this repo a ⭐️!
-- Follow us on social media:
- - Twitter: [@openfeature](https://twitter.com/openfeature)
- - LinkedIn: [OpenFeature](https://www.linkedin.com/company/openfeature/)
-- Join us on [Slack](https://cloud-native.slack.com/archives/C0344AANLA1)
-- For more check out our [community page](https://openfeature.dev/community/)
-
-## 🤝 Contributing
-
-Interested in contributing? Great, we'd love your help! To get started, take a look at the [CONTRIBUTING](CONTRIBUTING.md) guide.
-
-### Thanks to everyone that has already contributed
-
-
-
-
-
-
-Made with [contrib.rocks](https://contrib.rocks).
-
-## Contacting us
-
-We hold regular meetings which you can see [here](https://github.com/open-feature/community/#meetings-and-events).
-
-We are also present on the `#openfeature` channel in the [CNCF slack](https://slack.cncf.io/).
-
-## 📜 License
-
-[Apache License 2.0](LICENSE)
-
-
-
-[openfeature-website]: https://openfeature.dev