Skip to content

Commit

Permalink
Merge branch 'main' into feat/gherkin_and_testcontainers
Browse files Browse the repository at this point in the history
  • Loading branch information
aepfli authored Nov 14, 2024
2 parents 7c809e8 + a17c0e7 commit fc445d4
Show file tree
Hide file tree
Showing 13 changed files with 465 additions and 39 deletions.
12 changes: 7 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
package:
- "hooks/openfeature-hooks-opentelemetry"
- "providers/openfeature-provider-flagd"
Expand All @@ -38,9 +38,10 @@ jobs:
python-version: ${{ matrix.python-version }}
cache: "pip"

- uses: bufbuild/buf-setup-action@v1.28.1
- uses: bufbuild/buf-action@v1
with:
github_token: ${{ github.token }}
setup_only: true

- name: Install hatch
run: pip install hatch
Expand All @@ -49,8 +50,9 @@ jobs:
run: hatch run cov
working-directory: ${{ matrix.package }}

- name: Upload coverage to Codecov
uses: codecov/[email protected]
- if: matrix.python-version == '3.11'
name: Upload coverage to Codecov
uses: codecov/[email protected]
with:
name: Code Coverage for ${{ matrix.package }} on Python ${{ matrix.python-version }}
directory: ${{ matrix.package }}
Expand All @@ -69,7 +71,7 @@ jobs:
cache: "pip"

- name: Run pre-commit
uses: pre-commit/[email protected].0
uses: pre-commit/[email protected].1

sast:
runs-on: ubuntu-latest
Expand Down
7 changes: 4 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
default_stages: [commit]
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.3
rev: v0.6.3
hooks:
- id: ruff
args: [--fix]
- id: ruff-format

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
rev: v4.6.0
hooks:
- id: check-toml
- id: check-yaml
- id: trailing-whitespace
- id: check-merge-conflict

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.9.0
rev: v1.11.2
hooks:
- id: mypy
args: [--python-version=3.8]
Expand All @@ -25,6 +25,7 @@ repos:
- opentelemetry-api
- types-protobuf
- types-PyYAML
- types-requests
- mmh3
- semver
- panzi-json-logic
Expand Down
3 changes: 2 additions & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"hooks/openfeature-hooks-opentelemetry": "0.1.3",
"providers/openfeature-provider-flagd": "0.1.5"
"providers/openfeature-provider-flagd": "0.1.5",
"providers/openfeature-provider-ofrep": "0.1.0"
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import typing

from typing_extensions import Protocol

from openfeature.evaluation_context import EvaluationContext
from openfeature.flag_evaluation import FlagResolutionDetails

from .grpc import GrpcResolver
from .in_process import InProcessResolver


class AbstractResolver(Protocol):
class AbstractResolver(typing.Protocol):
def shutdown(self) -> None: ...

def resolve_boolean_details(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging
import typing
from dataclasses import dataclass

import mmh3
import semver
Expand All @@ -10,6 +11,12 @@
logger = logging.getLogger("openfeature.contrib")


@dataclass
class Fraction:
variant: str
weight: int = 1


def fractional(data: dict, *args: JsonLogicArg) -> typing.Optional[str]:
if not args:
logger.error("No arguments provided to fractional operator.")
Expand All @@ -32,28 +39,51 @@ def fractional(data: dict, *args: JsonLogicArg) -> typing.Optional[str]:
return None

hash_ratio = abs(mmh3.hash(bucket_by)) / (2**31 - 1)
bucket = int(hash_ratio * 100)
bucket = hash_ratio * 100

total_weight = 0
fractions = []
for arg in args:
if (
not isinstance(arg, (tuple, list))
or len(arg) != 2
or not isinstance(arg[0], str)
or not isinstance(arg[1], int)
):
logger.error("Fractional variant weights must be (str, int) tuple")
return None
variant_weights: typing.Tuple[typing.Tuple[str, int]] = args # type: ignore[assignment]

range_end = 0
for variant, weight in variant_weights:
range_end += weight
fraction = _parse_fraction(arg)
if fraction:
fractions.append(fraction)
total_weight += fraction.weight

range_end: float = 0
for fraction in fractions:
range_end += fraction.weight * 100 / total_weight
if bucket < range_end:
return variant
return fraction.variant

return None


def _parse_fraction(arg: JsonLogicArg) -> typing.Optional[Fraction]:
if not isinstance(arg, (tuple, list)) or not arg:
logger.error(
"Fractional variant weights must be (str, int) tuple or [str] list"
)
return None

if not isinstance(arg[0], str):
logger.error(
"Fractional variant identifier (first element) isn't of type 'str'"
)
return None

if len(arg) >= 2 and not isinstance(arg[1], int):
logger.error(
"Fractional variant weight value (second element) isn't of type 'int'"
)
return None

fraction = Fraction(variant=arg[0])
if len(arg) >= 2:
fraction.weight = arg[1]

return fraction


def starts_with(data: dict, *args: JsonLogicArg) -> typing.Optional[bool]:
def f(s1: str, s2: str) -> bool:
return s1.startswith(s2)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"flags": {
"basic-flag": {
"state": "ENABLED",
"variants": {
"default": "default",
"true": "true",
"false": "false"
},
"defaultVariant": "default",
"targeting": {
"fractional": [[]]
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"flags": {
"basic-flag": {
"state": "ENABLED",
"variants": {
"default": "default",
"true": "true",
"false": "false"
},
"defaultVariant": "default",
"targeting": {
"fractional": [
["a", "one"],
["b", "one"]
]
}
}
}
}
2 changes: 2 additions & 0 deletions providers/openfeature-provider-flagd/tests/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ def test_file_load_errors(file_name: str):
"invalid-semver-args.json",
"invalid-stringcomp-args.json",
"invalid-fractional-args.json",
"invalid-fractional-args-wrong-content.json",
"invalid-fractional-weights.json",
"invalid-fractional-weights-strings.json",
],
)
def test_json_logic_parse_errors(file_name: str):
Expand Down
10 changes: 10 additions & 0 deletions providers/openfeature-provider-ofrep/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
# Changelog

## 0.1.0 (2024-10-02)


### ✨ New Features

* add initial skeleton for OFREP provider ([#86](https://github.com/open-feature/python-sdk-contrib/issues/86)) ([00a5a18](https://github.com/open-feature/python-sdk-contrib/commit/00a5a18a76ef1435de67f312e384a97823bd185b))
* implement basic functionality of OFREP provider ([#88](https://github.com/open-feature/python-sdk-contrib/issues/88)) ([cb42cc0](https://github.com/open-feature/python-sdk-contrib/commit/cb42cc0001e19793f391351a1ce5bafe1831025f))

## Changelog
3 changes: 3 additions & 0 deletions providers/openfeature-provider-ofrep/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ classifiers = [
keywords = []
dependencies = [
"openfeature-sdk>=0.7.0",
"requests"
]
requires-python = ">=3.8"

Expand All @@ -30,6 +31,8 @@ Homepage = "https://github.com/open-feature/python-sdk-contrib"
dependencies = [
"coverage[toml]>=6.5",
"pytest",
"requests-mock",
"types-requests",
]

[tool.hatch.envs.default.scripts]
Expand Down
Loading

0 comments on commit fc445d4

Please sign in to comment.