• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Unleash / unleash-client-python / 6783227644

07 Nov 2023 10:31AM UTC coverage: 96.892% (+0.2%) from 96.684%
6783227644

Pull #285

github

pre-commit-ci[bot]
[pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
Pull Request #285: feat: add is_feature_enabled to variant response

3 of 4 new or added lines in 3 files covered. (75.0%)

904 of 933 relevant lines covered (96.89%)

0.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.77
/UnleashClient/variants/Variants.py
1
# pylint: disable=invalid-name, too-few-public-methods
2
import copy
1✔
3
import random
1✔
4
from typing import Dict, Optional  # noqa: F401
1✔
5

6
from UnleashClient import utils
1✔
7
from UnleashClient.constants import DISABLED_VARIATION
1✔
8

9
VARIANT_HASH_SEED = 86028157
1✔
10

11

12
class Variants:
1✔
13
    def __init__(
1✔
14
        self, variants_list: list, group_id: str, is_feature_variants: bool = True
15
    ) -> None:
16
        """
17
        Represents an A/B test
18

19
        variants_list = From the strategy document.
20
        """
21
        self.variants = variants_list
1✔
22
        self.group_id = group_id
1✔
23
        self.is_feature_variants = is_feature_variants
1✔
24

25
    def _apply_overrides(self, context: dict) -> dict:
1✔
26
        """
27
        Figures out if an override should be applied based on a context.
28

29
        Notes:
30
            - This matches only the first variant found.
31
        """
32
        variants_with_overrides = [x for x in self.variants if "overrides" in x.keys()]
1✔
33
        override_variant = {}  # type: Dict
1✔
34

35
        for variant in variants_with_overrides:
1✔
36
            for override in variant["overrides"]:
1✔
37
                identifier = utils.get_identifier(override["contextName"], context)
1✔
38
                if identifier in override["values"]:
1✔
39
                    override_variant = variant
1✔
40

41
        return override_variant
1✔
42

43
    @staticmethod
1✔
44
    def _get_seed(context: dict, stickiness_selector: str = "default") -> str:
1✔
45
        """Grabs seed value from context."""
46
        seed = ""
1✔
47

48
        if stickiness_selector == "default":
1✔
49
            if "userId" in context:
1✔
50
                seed = context["userId"]
1✔
51
            elif "sessionId" in context:
1✔
52
                seed = context["sessionId"]
1✔
53
            elif "remoteAddress" in context:
1✔
54
                seed = context["remoteAddress"]
1✔
55
            else:
56
                seed = str(random.random() * 10000)
1✔
57
        elif stickiness_selector == "random":
1✔
58
            seed = str(random.random() * 10000)
×
59
        else:
60
            seed = (
1✔
61
                context.get(stickiness_selector)
62
                or context.get("properties")[stickiness_selector]
63
            )
64

65
        return seed
1✔
66

67
    @staticmethod
1✔
68
    def _format_variation(variation: dict, flag_status: Optional[bool] = None) -> dict:
1✔
69
        formatted_variation = copy.deepcopy(variation)
1✔
70
        del formatted_variation["weight"]
1✔
71
        if "overrides" in formatted_variation:
1✔
72
            del formatted_variation["overrides"]
1✔
73
        if "stickiness" in formatted_variation:
1✔
74
            del formatted_variation["stickiness"]
1✔
75
        if "enabled" not in formatted_variation and flag_status is not None:
1✔
76
            formatted_variation["enabled"] = flag_status
1✔
77
        return formatted_variation
1✔
78

79
    def get_variant(self, context: dict, flag_status: Optional[bool] = None) -> dict:
1✔
80
        """
81
        Determines what variation a user is in.
82

83
        :param context:
84
        :param flag_status:
85
        :return:
86
        """
87
        if self.variants:
1✔
88
            override_variant = self._apply_overrides(context)
1✔
89
            if override_variant:
1✔
90
                return self._format_variation(override_variant, flag_status)
1✔
91

92
            total_weight = sum(x["weight"] for x in self.variants)
1✔
93
            if total_weight <= 0:
1✔
NEW
94
                return DISABLED_VARIATION
×
95

96
            stickiness_selector = (
1✔
97
                self.variants[0]["stickiness"]
98
                if "stickiness" in self.variants[0].keys()
99
                else "default"
100
            )
101

102
            target = utils.normalized_hash(
1✔
103
                self._get_seed(context, stickiness_selector),
104
                self.group_id,
105
                total_weight,
106
                seed=VARIANT_HASH_SEED,
107
            )
108
            counter = 0
1✔
109
            for variation in self.variants:
1✔
110
                counter += variation["weight"]
1✔
111

112
                if counter >= target:
1✔
113
                    return self._format_variation(variation, flag_status)
1✔
114

115
        # Catch all return.
116
        return DISABLED_VARIATION
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc