Repository: Unleash/unleash-client-python
Pull request #237 (2023-02-24 11:43:24)

feat: Extend Feature object with new attributes
# Description

Currently, there is no way to get answers to the question - **Whether impression data is enabled?**

The good news is that this information is provided so we can store it and use it if needed.

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

# How Has This Been Tested?

Please describe the tests that you ran to verify your changes.

- [x] Unit tests
- [x] Spec Tests
- [ ] Integration tests / Manual Tests

# Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

akalex: > stale usually isn't actually used meaningfully by the SDKs, it seems like you're wanting to get your hands on this property within the SDK so I'm super curious, what's your usecase here? I'm not against exposing them but usually when I see this kind of pull request, the SDK is being used for something we didn't design them for

The indention to open this PR mainly was issued by the absence of possibility in Python SDK to get impression data and have no clue when it will be added. So, I learned that extra information is available as part of the data pulled by the provisioning loader, but the object `Feature` does not preserve that information. 
Maybe I use SDK improperly, and you can advise what would be a better approach to get to know about Impression Data. Thank you in advance.


sighphyre: > > This seems to add the property for impression data but it doesn't actually add the functionality. Was that intended?
> 
> > stale usually isn't actually used meaningfully by the SDKs, it seems like you're wanting to get your hands on this property within the SDK so I'm super curious, what's your usecase here? I'm not against exposing them but usually when I see this kind of pull request, the SDK is being used for something we didn't design them for
> 
> The intention to open this PR mainly was issued by the absence of possibility in Python SDK to get impression data and have no clue when it will be added. So, I learned that extra information is available as part of the data pulled by the provisioning loader, but the object `Feature` does not preserve that information. Maybe I misuse SDK, and you can advise what would be a better approach to get to know about Impression Data. I really appreciate any help you can provide.

Right, this sounds like what you're doing here is starting the work/giving us a gentle nudge on implementing impression data in this SDK? That makes a lot of sense, that's absolutely not a misuse of this SDK. But this is a bigger feature than just implementing the properties that come back from the server. It's probably worth going going over the PRs that add this feature to the dotnet SDK (https://github.com/Unleash/unleash-client-dotnet/pull/113) and the node SDK (https://github.com/Unleash/unleash-client-node/pull/336) if you're interested in the technical details here and are looking to implement this here.

What probably needs to be done here is exposing the impression data property (done already), adding an event system or using Python built ins to expose a stream of events and then injecting the events into that system when the toggle is checked.

It sounds like this is also a request for us to implement this feature, so I've opened a ticket here for it: https://github.com/Unleash/unleash-client-python/issues/238 so that if this is more work than you had wanted to get involved we can track it internally.
akalex: > Right, this sounds like what you're doing here is starting the work/giving us a gentle nudge on implementing impression data in this SDK? That makes a lot of sense, that's absolutely not a misuse of this SDK. But this is a bigger feature than just implementing the properties that come back from the server. It's probably worth going going over the PRs that add this feature to the dotnet SDK (https://github.com/Unleash/unleash-client-dotnet/pull/113) and the node SDK (https://github.com/Unleash/unleash-client-node/pull/336) if you're interested in the technical details here and are looking to implement this here.

> What probably needs to be done here is exposing the impression data property (done already), adding an event system or using Python built ins to expose a stream of events and then injecting the events into that system when the toggle is checked.

> It sounds like this is also a request for us to implement this feature, so I've opened a ticket here for it: https://github.com/Unleash/unleash-client-python/issues/238 so that if this is more work than you had wanted to get involved we can track it internally.

You are correct that would be absolutely great if you could prioritise some work around Impression Data, and thanks for opening a ticket.

On the other hand, I still do not see a strong reason why the `Feature` object should not be extended with the properties that the object already has. Such changes neither break interface nor go against the rules but rather provides fair compromise and room for maneuvers.

What are your thoughts on that?
sighphyre: @akalex I'm very open to including the inclusion of of the impression data property before we've implemented the feature itself but I'm still not sure what including the stale property would add. Do you see a use case here that I'm missing? 
akalex: > @akalex I'm very open to including the inclusion of of the impression data property before we've implemented the feature itself but I'm still not sure what including the stale property would add. Do you see a use case here that I'm missing?

@sighphyre that's a great question, I don't have a good example from the top of my head. Let me get rid of the `stale` property.
akalex: > > @akalex I'm very open to including the inclusion of of the impression data property before we've implemented the feature itself but I'm still not sure what including the stale property would add. Do you see a use case here that I'm missing?
> 
> @sighphyre that's a great question, I don't have a good example from the top of my head. Let me get rid of the `stale` property.

@sighphyre this is done. could you take a look at it once you have a chance
sighphyre: @akalex Thanks so much for doing the changes. This looks good to me. To keep you in the loop, I've raised the impression data feature with the team internally to look into next week, we'll probably just build on top of this PR

Patch:
diff --git a/UnleashClient/features/Feature.py b/UnleashClient/features/Feature.py
index 16d932c..4dc9f32 100644
--- a/UnleashClient/features/Feature.py
+++ b/UnleashClient/features/Feature.py
@@ -1,4 +1,6 @@
 # pylint: disable=invalid-name
+from typing import Optional
+
 from UnleashClient.variants import Variants
 from UnleashClient.utils import LOGGER
 from UnleashClient.constants import DISABLED_VARIATION
@@ -10,13 +12,15 @@ class Feature:
                  name: str,
                  enabled: bool,
                  strategies: list,
-                 variants: Variants = None) -> None:
+                 variants: Optional[Variants] = None,
+                 impression_data: bool = False) -> None:
         """
         A representation of a feature object
 
         :param name: Name of the feature.
         :param enabled: Whether feature is enabled.
         :param strategies: List of sub-classed Strategy objects representing feature strategies.
+        :param impression_data: Whether impression data is enabled.
         """
         # Experiment information
         self.name = name
@@ -24,6 +28,9 @@ class Feature:
         self.strategies = strategies
         self.variants = variants
 
+        # Additional information
+        self.impression_data = impression_data
+
         # Stats tracking
         self.yes_count = 0
         self.no_count = 0
diff --git a/UnleashClient/loader.py b/UnleashClient/loader.py
index 7af7251..335864a 100644
--- a/UnleashClient/loader.py
+++ b/UnleashClient/loader.py
@@ -59,11 +59,13 @@ def _create_feature(provisioning: dict,
     else:
         variant = None
 
-    return Feature(name=provisioning["name"],
-                   enabled=provisioning["enabled"],
-                   strategies=parsed_strategies,
-                   variants=variant
-                   )
+    return Feature(
+        name=provisioning["name"],
+        enabled=provisioning["enabled"],
+        strategies=parsed_strategies,
+        variants=variant,
+        impression_data=provisioning.get("impressionData", False),
+    )
 
 
 def load_features(cache: BaseCache,
@@ -119,6 +121,8 @@ def load_features(cache: BaseCache,
                 parsed_features[feature]['name']
             )
 
+        feature_for_update.impression_data = parsed_features[feature].get("impressionData", False)
+
     # Handle creation or deletions
     new_features = list(set(feature_names) - set(feature_toggles.keys()))
 


Test patch:
diff --git a/tests/unit_tests/test_features.py b/tests/unit_tests/test_features.py
index 4217986..6d559e0 100644
--- a/tests/unit_tests/test_features.py
+++ b/tests/unit_tests/test_features.py
@@ -32,6 +32,7 @@ def test_create_feature_true(test_feature):
 
     my_feature.reset_stats()
     assert my_feature.yes_count == 0
+    assert not my_feature.impression_data
 
 
 def test_create_feature_false(test_feature):
diff --git a/tests/unit_tests/test_loader.py b/tests/unit_tests/test_loader.py
index 36a7676..fdf6f7b 100644
--- a/tests/unit_tests/test_loader.py
+++ b/tests/unit_tests/test_loader.py
@@ -36,6 +36,8 @@ def test_loader_initialization(cache_full):  # noqa: F811
         if isinstance(strategy, Variants):
             assert strategy.variants
 
+        assert feature.impression_data is False
+
 
 def test_loader_refresh_strategies(cache_full):  # noqa: F811
     # Set up variables
diff --git a/tests/utilities/mocks/mock_all_features.py b/tests/utilities/mocks/mock_all_features.py
index 1ad2b7f..03ca9f0 100644
--- a/tests/utilities/mocks/mock_all_features.py
+++ b/tests/utilities/mocks/mock_all_features.py
@@ -1,214 +1,223 @@
-MOCK_ALL_FEATURES = \
-{
-  "version": 1,
-  "features": [
-    {
-      "name": "ApplicationHostname",
-      "description": "Application Hostname strategy",
-      "enabled": True,
-      "strategies": [
+MOCK_ALL_FEATURES = {
+    "version": 1,
+    "features": [
         {
-          "name": "applicationHostname",
-          "parameters": {
-            "hostNames": "iMacPro.local,test1,test2"
-          }
-        }
-      ],
-      "createdAt": "2018-10-09T06:05:14.757Z"
-    },
-    {
-      "name": "Default",
-      "description": "Default feature toggle",
-      "enabled": True,
-      "strategies": [
+            "name": "ApplicationHostname",
+            "description": "Application Hostname strategy",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "applicationHostname",
+                    "parameters": {
+                        "hostNames": "iMacPro.local,test1,test2"
+                    }
+                }
+            ],
+            "createdAt": "2018-10-09T06:05:14.757Z",
+            "impressionData": False
+        },
         {
-          "name": "default",
-          "parameters": {}
-        }
-      ],
-      "createdAt": "2018-10-09T06:04:05.667Z"
-    },
-    {
-      "name": "GradualRolloutRandom",
-      "description": "Gradual Rollout Random example",
-      "enabled": True,
-      "strategies": [
+            "name": "Default",
+            "description": "Default feature toggle",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "default",
+                    "parameters": {}
+                }
+            ],
+            "createdAt": "2018-10-09T06:04:05.667Z",
+            "impressionData": False
+        },
         {
-          "name": "gradualRolloutRandom",
-          "parameters": {
-            "percentage": 50
-          }
-        }
-      ],
-      "createdAt": "2018-10-09T06:05:37.637Z"
-    },
-    {
-      "name": "GradualRolloutSessionId",
-      "description": "SessionID check!",
-      "enabled": True,
-      "strategies": [
+            "name": "GradualRolloutRandom",
+            "description": "Gradual Rollout Random example",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "gradualRolloutRandom",
+                    "parameters": {
+                        "percentage": 50
+                    }
+                }
+            ],
+            "createdAt": "2018-10-09T06:05:37.637Z",
+            "impressionData": False
+        },
         {
-          "name": "gradualRolloutSessionId",
-          "parameters": {
-            "percentage": 50,
-            "groupId": "GradualRolloutSessionId"
-          }
-        }
-      ],
-      "createdAt": "2018-10-09T06:06:51.057Z"
-    },
-    {
-      "name": "GradualRolloutUserID",
-      "description": "GradualRolloutUserID strategy",
-      "enabled": True,
-      "strategies": [
+            "name": "GradualRolloutSessionId",
+            "description": "SessionID check!",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "gradualRolloutSessionId",
+                    "parameters": {
+                        "percentage": 50,
+                        "groupId": "GradualRolloutSessionId"
+                    }
+                }
+            ],
+            "createdAt": "2018-10-09T06:06:51.057Z",
+            "impressionData": False
+        },
         {
-          "name": "gradualRolloutUserId",
-          "parameters": {
-            "percentage": 50,
-            "groupId": "GradualRolloutUserID"
-          }
-        }
-      ],
-      "createdAt": "2018-10-09T06:07:17.520Z"
-    },
-    {
-      "name": "RemoteAddress",
-      "description": "RemoteAddress strategies",
-      "enabled": True,
-      "strategies": [
+            "name": "GradualRolloutUserID",
+            "description": "GradualRolloutUserID strategy",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "gradualRolloutUserId",
+                    "parameters": {
+                        "percentage": 50,
+                        "groupId": "GradualRolloutUserID"
+                    }
+                }
+            ],
+            "createdAt": "2018-10-09T06:07:17.520Z",
+            "impressionData": False
+        },
         {
-          "name": "remoteAddress",
-          "parameters": {
-            "IPs": "69.208.0.0/29,70.208.1.1,2001:db8:1234::/48,2002:db8:1234:0000:0000:0000:0000:0001"
-          }
-        }
-      ],
-      "createdAt": "2018-10-09T06:08:42.398Z"
-    },
-    {
-      "name": "UserWithId",
-      "description": "UserWithId strategies",
-      "enabled": True,
-      "strategies": [
+            "name": "RemoteAddress",
+            "description": "RemoteAddress strategies",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "remoteAddress",
+                    "parameters": {
+                        "IPs": "69.208.0.0/29,70.208.1.1,2001:db8:1234::/48,2002:db8:1234:0000:0000:0000:0000:0001"
+                    }
+                }
+            ],
+            "createdAt": "2018-10-09T06:08:42.398Z",
+            "impressionData": False
+        },
         {
-          "name": "userWithId",
-          "parameters": {
-            "userIds": "meep@meep.com,test@test.com,wat@wat.com"
-          }
-        }
-      ],
-      "createdAt": "2018-10-09T06:09:19.203Z"
-    },
-    {
-      "name": "FlexibleRollout",
-      "description": "FlexibleRollout strategies",
-      "enabled": True,
-      "strategies": [
+            "name": "UserWithId",
+            "description": "UserWithId strategies",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "userWithId",
+                    "parameters": {
+                        "userIds": "meep@meep.com,test@test.com,wat@wat.com"
+                    }
+                }
+            ],
+            "createdAt": "2018-10-09T06:09:19.203Z",
+            "impressionData": False
+        },
         {
-          "name": "flexibleRollout",
-          "parameters": {
-            "rollout": "21",
-            "stickiness": "userId",
-            "groupId": "ivantest"
-          },
-          "constraints": [
-            {
-              "contextName": "environment",
-              "operator": "IN",
-              "values": [
-                "staging",
-                "prod"
-              ]
-            },
-            {
-              "contextName": "userId",
-              "operator": "NOT_IN",
-              "values": [
-                "1",
-                "2",
-                "3"
-              ]
-            },
-            {
-              "contextName": "userId",
-              "operator": "IN",
-              "values": [
-                "4",
-                "5",
-                "6"
-              ]
-            },
-            {
-              "contextName": "appName",
-              "operator": "IN",
-              "values": [
-                "test"
-              ]
-            }
-          ]
-        }
-      ],
-      "variants": None,
-      "createdAt": "2019-10-05T07:30:29.896Z"
-    },
-    {
-      "name": "Variations",
-      "description": "Test variation",
-      "enabled": True,
-      "strategies": [
-          {
-              "name": "default"
-          }
-      ],
-      "variants": [
-          {
-              "name": "VarA",
-              "weight": 34,
-              "payload": {
-                  "type": "string",
-                  "value": "Test1"
-              },
-              "overrides": [
-                  {
-                      "contextName": "userId",
-                      "values": [
-                          "ivanklee86@gmail.com",
-                          "ivan@aaptiv.com"
-                      ]
-                  }
-              ]
-          },
-          {
-              "name": "VarB",
-              "weight": 33,
-              "payload": {
-                  "type": "string",
-                  "value": "Test 2"
-              }
-          },
-          {
-              "name": "VarC",
-              "weight": 33,
-              "payload": {
-                  "type": "string",
-                  "value": "Test 3"
-              }
-          }
-      ],
-      "createdAt": "2019-10-25T13:22:02.035Z"
-  },
-  {
-    "name": "Garbage",
-    "description": "Invalid strategy",
-    "enabled": True,
-    "strategies": [
-      {
-        "name": "blargwatisdis",
-        "parameters": {}
-      }
-    ],
-    "createdAt": "2018-10-09T06:04:05.667Z"
-  },
-  ]
+            "name": "FlexibleRollout",
+            "description": "FlexibleRollout strategies",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "flexibleRollout",
+                    "parameters": {
+                        "rollout": "21",
+                        "stickiness": "userId",
+                        "groupId": "ivantest"
+                    },
+                    "constraints": [
+                        {
+                            "contextName": "environment",
+                            "operator": "IN",
+                            "values": [
+                                "staging",
+                                "prod"
+                            ]
+                        },
+                        {
+                            "contextName": "userId",
+                            "operator": "NOT_IN",
+                            "values": [
+                                "1",
+                                "2",
+                                "3"
+                            ]
+                        },
+                        {
+                            "contextName": "userId",
+                            "operator": "IN",
+                            "values": [
+                                "4",
+                                "5",
+                                "6"
+                            ]
+                        },
+                        {
+                            "contextName": "appName",
+                            "operator": "IN",
+                            "values": [
+                                "test"
+                            ]
+                        }
+                    ]
+                }
+            ],
+            "variants": None,
+            "createdAt": "2019-10-05T07:30:29.896Z",
+            "impressionData": False
+        },
+        {
+            "name": "Variations",
+            "description": "Test variation",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "default"
+                }
+            ],
+            "variants": [
+                {
+                    "name": "VarA",
+                    "weight": 34,
+                    "payload": {
+                        "type": "string",
+                        "value": "Test1"
+                    },
+                    "overrides": [
+                        {
+                            "contextName": "userId",
+                            "values": [
+                                "ivanklee86@gmail.com",
+                                "ivan@aaptiv.com"
+                            ]
+                        }
+                    ]
+                },
+                {
+                    "name": "VarB",
+                    "weight": 33,
+                    "payload": {
+                        "type": "string",
+                        "value": "Test 2"
+                    }
+                },
+                {
+                    "name": "VarC",
+                    "weight": 33,
+                    "payload": {
+                        "type": "string",
+                        "value": "Test 3"
+                    }
+                }
+            ],
+            "createdAt": "2019-10-25T13:22:02.035Z",
+            "impressionData": False
+        },
+        {
+            "name": "Garbage",
+            "description": "Invalid strategy",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "blargwatisdis",
+                    "parameters": {}
+                }
+            ],
+            "createdAt": "2018-10-09T06:04:05.667Z",
+            "impressionData": False
+        },
+    ]
 }
diff --git a/tests/utilities/mocks/mock_bootstrap.json b/tests/utilities/mocks/mock_bootstrap.json
index bcf024d..3ecae78 100644
--- a/tests/utilities/mocks/mock_bootstrap.json
+++ b/tests/utilities/mocks/mock_bootstrap.json
@@ -5,7 +5,6 @@
           "name":"ivan-project",
           "type":"release",
           "enabled": true,
-          "stale": false,
           "strategies":[
              {
                 "name":"default",
@@ -16,7 +15,8 @@
           ],
           "variants":[
              
-          ]
+          ],
+          "impressionData": false
        }
     ]
  }
\ No newline at end of file
diff --git a/tests/utilities/mocks/mock_custom_strategy.py b/tests/utilities/mocks/mock_custom_strategy.py
index ede413b..ee0d5a4 100644
--- a/tests/utilities/mocks/mock_custom_strategy.py
+++ b/tests/utilities/mocks/mock_custom_strategy.py
@@ -1,75 +1,79 @@
 MOCK_CUSTOM_STRATEGY = {
-  "version": 1,
-  "features": [
-    {
-      "name": "CustomToggle",
-      "description": "CustomToggle Test",
-      "enabled": True,
-      "strategies": [
+    "version": 1,
+    "features": [
         {
-          "name": "amIACat",
-          "parameters": {
-            "sound": "meow,nyaa"
-          },
-          "constraints": [
-            {
-              "contextName": "environment",
-              "operator": "IN",
-              "values": [
-                "staging",
-                "prod"
-              ]
-            }
-          ]
-        }
-      ],
-      "createdAt": "2018-10-13T10:15:29.009Z"
-    },
-    {
-      "name": "CustomToggleWarning",
-      "description": "CustomToggle Warning Test",
-      "enabled": True,
-      "strategies": [
-        {
-          "name": "amIADog",
-          "parameters": {
-            "sound": "arf,bark"
-          }
-        }
-      ],
-      "createdAt": "2018-10-13T10:15:29.009Z"
-    },
-    {
-      "name": "CustomToggleWarningMultiStrat",
-      "description": "CustomToggle Warning Test",
-      "enabled": True,
-      "strategies": [
+            "name": "CustomToggle",
+            "description": "CustomToggle Test",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "amIACat",
+                    "parameters": {
+                        "sound": "meow,nyaa"
+                    },
+                    "constraints": [
+                        {
+                            "contextName": "environment",
+                            "operator": "IN",
+                            "values": [
+                                "staging",
+                                "prod"
+                            ]
+                        }
+                    ]
+                }
+            ],
+            "createdAt": "2018-10-13T10:15:29.009Z",
+            "impressionData": False
+        },
         {
-          "name": "amIADog",
-          "parameters": {
-            "sound": "arf,bark"
-          }
+            "name": "CustomToggleWarning",
+            "description": "CustomToggle Warning Test",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "amIADog",
+                    "parameters": {
+                        "sound": "arf,bark"
+                    }
+                }
+            ],
+            "createdAt": "2018-10-13T10:15:29.009Z",
+            "impressionData": False
         },
         {
-          "name": "default",
-          "parameters": {}
-        }
-      ],
-      "createdAt": "2018-10-13T10:15:29.009Z"
-    },
-    {
-      "name": "UserWithId",
-      "description": "UserWithId",
-      "enabled": True,
-      "strategies": [
+            "name": "CustomToggleWarningMultiStrat",
+            "description": "CustomToggle Warning Test",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "amIADog",
+                    "parameters": {
+                        "sound": "arf,bark"
+                    }
+                },
+                {
+                    "name": "default",
+                    "parameters": {}
+                }
+            ],
+            "createdAt": "2018-10-13T10:15:29.009Z",
+            "impressionData": False
+        },
         {
-          "name": "userWithId",
-          "parameters": {
-            "userIds": "meep@meep.com,test@test.com,ivan@ivan.com"
-          }
+            "name": "UserWithId",
+            "description": "UserWithId",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "userWithId",
+                    "parameters": {
+                        "userIds": "meep@meep.com,test@test.com,ivan@ivan.com"
+                    }
+                }
+            ],
+            "createdAt": "2018-10-11T09:33:51.171Z",
+            "impressionData": False
         }
-      ],
-      "createdAt": "2018-10-11T09:33:51.171Z"
-    }
-  ]
+    ]
 }
diff --git a/tests/utilities/mocks/mock_features.py b/tests/utilities/mocks/mock_features.py
index 62d6860..e84c7af 100644
--- a/tests/utilities/mocks/mock_features.py
+++ b/tests/utilities/mocks/mock_features.py
@@ -11,7 +11,8 @@ MOCK_FEATURE_RESPONSE = {
                     "parameters": {}
                 }
             ],
-            "createdAt": "2018-10-04T01:27:28.477Z"
+            "createdAt": "2018-10-04T01:27:28.477Z",
+            "impressionData": False
         },
         {
             "name": "testFlag2",
@@ -25,7 +26,8 @@ MOCK_FEATURE_RESPONSE = {
                     }
                 }
             ],
-            "createdAt": "2018-10-04T11:03:56.062Z"
+            "createdAt": "2018-10-04T11:03:56.062Z",
+            "impressionData": False
         },
         {
             "name": "testContextFlag",
@@ -39,7 +41,8 @@ MOCK_FEATURE_RESPONSE = {
                     }
                 }
             ],
-            "createdAt": "2018-10-04T01:27:28.477Z"
+            "createdAt": "2018-10-04T01:27:28.477Z",
+            "impressionData": False
         },
         {
             "name": "testConstraintFlag",
@@ -59,57 +62,59 @@ MOCK_FEATURE_RESPONSE = {
                     ],
                 },
             ],
-            "createdAt": "2018-10-04T01:27:28.477Z"
+            "createdAt": "2018-10-04T01:27:28.477Z",
+            "impressionData": False
         },
         {
-          "name": "testVariations",
-          "description": "Test variation",
-          "enabled": True,
-          "strategies": [
-              {
-                  "name": "userWithId",
-                  "parameters": {
-                      "userIds": "2"
-                  }
-              }
-          ],
-          "variants": [
-              {
-                  "name": "VarA",
-                  "weight": 34,
-                  "payload": {
-                      "type": "string",
-                      "value": "Test1"
-                  },
-                  "overrides": [
-                      {
-                          "contextName": "userId",
-                          "values": [
-                              "ivanklee86@gmail.com",
-                              "ivan@aaptiv.com"
-                          ]
-                      }
-                  ]
-              },
-              {
-                  "name": "VarB",
-                  "weight": 33,
-                  "payload": {
-                      "type": "string",
-                      "value": "Test 2"
-                  }
-              },
-              {
-                  "name": "VarC",
-                  "weight": 33,
-                  "payload": {
-                      "type": "string",
-                      "value": "Test 3"
-                  }
-              }
-          ],
-          "createdAt": "2019-10-25T13:22:02.035Z"
-      }
+            "name": "testVariations",
+            "description": "Test variation",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "userWithId",
+                    "parameters": {
+                        "userIds": "2"
+                    }
+                }
+            ],
+            "variants": [
+                {
+                    "name": "VarA",
+                    "weight": 34,
+                    "payload": {
+                        "type": "string",
+                        "value": "Test1"
+                    },
+                    "overrides": [
+                        {
+                            "contextName": "userId",
+                            "values": [
+                                "ivanklee86@gmail.com",
+                                "ivan@aaptiv.com"
+                            ]
+                        }
+                    ]
+                },
+                {
+                    "name": "VarB",
+                    "weight": 33,
+                    "payload": {
+                        "type": "string",
+                        "value": "Test 2"
+                    }
+                },
+                {
+                    "name": "VarC",
+                    "weight": 33,
+                    "payload": {
+                        "type": "string",
+                        "value": "Test 3"
+                    }
+                }
+            ],
+            "createdAt": "2019-10-25T13:22:02.035Z",
+            "impressionData": False
+        }
     ]
 }
 
@@ -132,7 +137,6 @@ MOCK_FEATURES_WITH_SEGMENTS_RESPONSE = {
             "name": "Test",
             "description": "",
             "project": "default",
-            "stale": False,
             "type": "release",
             "variants": []
         }
@@ -180,24 +184,25 @@ MOCK_FEATURES_WITH_SEGMENTS_RESPONSE = {
 }
 
 MOCK_FEATURE_RESPONSE_PROJECT = {
-   "version":1,
-   "features":[
-      {
-         "name":"ivan-project",
-         "type":"release",
-         "enabled": True,
-         "stale": False,
-         "strategies":[
-            {
-               "name":"default",
-               "parameters":{
+    "version": 1,
+    "features": [
+        {
+            "name": "ivan-project",
+            "type": "release",
+            "enabled": True,
+            "strategies": [
+                {
+                    "name": "default",
+                    "parameters": {
 
-               }
-            }
-         ],
-         "variants":[
+                    }
+                }
+            ],
+            "variants": [
 
-         ]
-      }
-   ]
-}
\ No newline at end of file
+            ],
+            "createdAt": "2023-01-24T06:40:25.331Z",
+            "impressionData": False
+        }
+    ]
+}