kameleoon-client-python 2.3.0__py2.py3-none-any.whl → 3.0.0__py2.py3-none-any.whl

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.
Files changed (50) hide show
  1. kameleoon/__init__.py +2 -1
  2. kameleoon/configuration/data_file.py +63 -0
  3. kameleoon/configuration/feature_flag.py +1 -0
  4. kameleoon/configuration/rule.py +5 -10
  5. kameleoon/configuration/rule_type.py +17 -0
  6. kameleoon/configuration/settings.py +15 -3
  7. kameleoon/configuration/variation_by_exposition.py +2 -2
  8. kameleoon/data/browser.py +22 -13
  9. kameleoon/data/conversion.py +27 -10
  10. kameleoon/data/custom_data.py +32 -34
  11. kameleoon/data/data.py +12 -15
  12. kameleoon/data/device.py +17 -11
  13. kameleoon/data/page_view.py +29 -9
  14. kameleoon/data/user_agent.py +10 -4
  15. kameleoon/defaults.py +0 -32
  16. kameleoon/exceptions.py +32 -57
  17. kameleoon/helpers/functions.py +10 -44
  18. kameleoon/helpers/multi_threading.py +61 -21
  19. kameleoon/helpers/nonce.py +12 -0
  20. kameleoon/helpers/repeat_timer.py +3 -1
  21. kameleoon/helpers/scheduler.py +67 -0
  22. kameleoon/helpers/visitor_code.py +26 -0
  23. kameleoon/kameleoon_client.py +1011 -0
  24. kameleoon/kameleoon_client_config.py +178 -0
  25. kameleoon/kameleoon_client_factory.py +57 -0
  26. kameleoon/middleware.py +23 -26
  27. kameleoon/real_time/real_time_configuration_service.py +3 -8
  28. kameleoon/sdk_version.py +1 -1
  29. kameleoon/targeting/conditions/browser_condition.py +5 -8
  30. kameleoon/targeting/conditions/conversion_condition.py +9 -9
  31. kameleoon/targeting/conditions/custom_datum.py +67 -58
  32. kameleoon/targeting/conditions/device_condition.py +6 -6
  33. kameleoon/targeting/conditions/exclusive_experiment.py +12 -13
  34. kameleoon/targeting/conditions/page_title_condition.py +10 -6
  35. kameleoon/targeting/conditions/page_url_condition.py +13 -6
  36. kameleoon/targeting/conditions/sdk_language_condition.py +1 -2
  37. kameleoon/targeting/conditions/string_value_condition.py +16 -17
  38. kameleoon/targeting/conditions/target_experiment.py +10 -11
  39. kameleoon/targeting/conditions/targeting_condition.py +3 -11
  40. kameleoon/targeting/conditions/unknown_condition.py +2 -1
  41. {kameleoon_client_python-2.3.0.dist-info → kameleoon_client_python-3.0.0.dist-info}/METADATA +25 -23
  42. kameleoon_client_python-3.0.0.dist-info/RECORD +64 -0
  43. kameleoon/client.py +0 -1374
  44. kameleoon/client_configuration.py +0 -26
  45. kameleoon/helpers/config.py +0 -28
  46. kameleoon/storage/varation_storage.py +0 -61
  47. kameleoon/storage/visitor_variation.py +0 -22
  48. kameleoon_client_python-2.3.0.dist-info/RECORD +0 -61
  49. {kameleoon_client_python-2.3.0.dist-info → kameleoon_client_python-3.0.0.dist-info}/WHEEL +0 -0
  50. {kameleoon_client_python-2.3.0.dist-info → kameleoon_client_python-3.0.0.dist-info}/top_level.txt +0 -0
kameleoon/__init__.py CHANGED
@@ -1,5 +1,6 @@
1
1
  """Kameleoon PYTHON SDK"""
2
2
 
3
3
  from .sdk_version import __version__ # noqa: F401
4
- from .client import KameleoonClient # noqa: F401
4
+ from .kameleoon_client import KameleoonClient # noqa: F401
5
+ from .kameleoon_client_config import KameleoonClientConfig # noqa: F401
5
6
  from .middleware import KameleoonWSGIMiddleware # noqa: F401
@@ -0,0 +1,63 @@
1
+ """Kameleoon Configuration"""
2
+
3
+ from typing import Any, Dict, Optional
4
+ from kameleoon.configuration.feature_flag import FeatureFlag
5
+ from kameleoon.configuration.settings import Settings
6
+ from kameleoon.exceptions import FeatureNotFound, FeatureEnvironmentDisabled
7
+
8
+
9
+ class DataFile:
10
+ """`DataFile` is a container for an actual client-configuration data"""
11
+
12
+ @staticmethod
13
+ def default(environment: Optional[str]) -> "DataFile":
14
+ """Creates new instance of `DataFile` initialized with default values"""
15
+ return DataFile(environment, Settings(), {})
16
+
17
+ @staticmethod
18
+ def from_json(environment: Optional[str], configuration: Dict[str, Any]) -> "DataFile":
19
+ """Creates new instance of `DataFile` initialized from the specified configuration JSON"""
20
+ settings = Settings(configuration.get("configuration"))
21
+ feature_flags = {
22
+ (feature_flag := FeatureFlag(jobj)).feature_key: feature_flag
23
+ for jobj in configuration.get("featureFlags") or []
24
+ }
25
+ return DataFile(environment, settings, feature_flags)
26
+
27
+ def __init__(self, environment: Optional[str], settings: Settings, feature_flags: Dict[str, FeatureFlag]) -> None:
28
+ self.__environment = environment # pylint: disable=W0238
29
+ self.__settings = settings
30
+ self.__feature_flags: Dict[str, FeatureFlag] = feature_flags
31
+ self.__has_any_targeted_delivery_rule = any(
32
+ rule.is_targeted_delivery
33
+ for ff in self.__feature_flags.values()
34
+ if ff.environment_enabled
35
+ for rule in ff.rules
36
+ )
37
+
38
+ @property
39
+ def settings(self) -> Settings:
40
+ """Returns settings"""
41
+ return self.__settings
42
+
43
+ @property
44
+ def feature_flags(self) -> Dict[str, FeatureFlag]:
45
+ """Returns dictionary of all feature flags stored by feature keys"""
46
+ return self.__feature_flags
47
+
48
+ @property
49
+ def has_any_targeted_delivery_rule(self) -> bool:
50
+ """Returns `True` if has a feature flag with a rule of the targeted delivery type, otherwise returns `False`"""
51
+ return self.__has_any_targeted_delivery_rule
52
+
53
+ def get_feature_flag(self, feature_key: str) -> FeatureFlag:
54
+ """
55
+ Returns feature flag with the specified feature key if it exists,
56
+ otherwise raises `FeatureNotFound` exception.
57
+ """
58
+ feature_flag = self.__feature_flags.get(feature_key)
59
+ if feature_flag is None:
60
+ raise FeatureNotFound(feature_key)
61
+ if not feature_flag.environment_enabled:
62
+ raise FeatureEnvironmentDisabled(feature_key, self.__environment)
63
+ return feature_flag
@@ -23,6 +23,7 @@ class FeatureFlag:
23
23
  self.variations: List[Variation] = Variation.from_array(
24
24
  dict_json.get("variations", [])
25
25
  )
26
+ self.environment_enabled = dict_json.get("environmentEnabled", False)
26
27
  self.rules: List[Rule] = Rule.from_array(dict_json.get("rules", []))
27
28
 
28
29
  def get_variation(self, key: str) -> Optional[Variation]:
@@ -1,7 +1,7 @@
1
1
  """Kameleoon Configuration"""
2
2
 
3
- from enum import Enum
4
3
  from typing import Any, List, Dict, Optional
4
+ from kameleoon.configuration.rule_type import RuleType, rule_type_from_literal
5
5
  from kameleoon.configuration.variation_by_exposition import VariationByExposition
6
6
  from kameleoon.targeting.models import Segment
7
7
 
@@ -11,12 +11,6 @@ class Rule:
11
11
  Rule is used for saving rule of feature flags (v2) with rules
12
12
  """
13
13
 
14
- class Type(Enum):
15
- """Possible types of rules"""
16
-
17
- EXPERIMENTATION = "EXPERIMENTATION"
18
- TARGETED_DELIVERY = "TARGETED_DELIVERY"
19
-
20
14
  @staticmethod
21
15
  def from_array(array: List[Dict[str, Any]]) -> List["Rule"]:
22
16
  """Create a list of Rules from the json array"""
@@ -26,7 +20,8 @@ class Rule:
26
20
  def __init__(self, dict_json: Dict[str, Any]):
27
21
  self.id_: int = dict_json["id"]
28
22
  self.order: int = dict_json.get("order", 0)
29
- self.type: str = dict_json.get("type", "")
23
+ type_literal: str = dict_json.get("type", "")
24
+ self.type = rule_type_from_literal(type_literal)
30
25
  self.exposition: float = dict_json.get("exposition", 0.0)
31
26
  self.experiment_id: int = dict_json.get("experimentId", 0)
32
27
  self.respool_time: Optional[int] = dict_json.get("respoolTime", None)
@@ -50,10 +45,10 @@ class Rule:
50
45
  def is_experimentation(self) -> bool:
51
46
  """Return `true` if rule is `experimentation` type"""
52
47
 
53
- return self.type == Rule.Type.EXPERIMENTATION.value
48
+ return self.type == RuleType.EXPERIMENTATION
54
49
 
55
50
  @property
56
51
  def is_targeted_delivery(self) -> bool:
57
52
  """Return `true` if rule is `targeted delivery` type"""
58
53
 
59
- return self.type == Rule.Type.TARGETED_DELIVERY.value
54
+ return self.type == RuleType.TARGETED_DELIVERY
@@ -0,0 +1,17 @@
1
+ """Kameleoon Configuration"""
2
+
3
+ from enum import Enum
4
+ from kameleoon.helpers.functions import enum_from_literal
5
+
6
+
7
+ class RuleType(Enum):
8
+ """Possible types of rules"""
9
+
10
+ UNKNOWN: None = None
11
+ EXPERIMENTATION = "EXPERIMENTATION"
12
+ TARGETED_DELIVERY = "TARGETED_DELIVERY"
13
+
14
+
15
+ def rule_type_from_literal(literal: str) -> RuleType:
16
+ """Converts rule type literal to RuleType value"""
17
+ return enum_from_literal(literal, RuleType, RuleType.UNKNOWN)
@@ -9,8 +9,20 @@ class Settings:
9
9
  state of real time update for site code and etc
10
10
  """
11
11
 
12
+ _CONSENT_TYPE_REQUIRED = "REQUIRED"
13
+
12
14
  # pylint: disable=R0903
13
15
  def __init__(self, configuration: Optional[Dict[str, Any]] = None):
14
- self.real_time_update: bool = bool(
15
- configuration and configuration.get("realTimeUpdate")
16
- )
16
+ self.__real_time_update: bool = bool(configuration and configuration.get("realTimeUpdate"))
17
+ self.__is_consent_required = (configuration is not None) and \
18
+ (configuration.get("consentType") == self._CONSENT_TYPE_REQUIRED)
19
+
20
+ @property
21
+ def real_time_update(self) -> bool:
22
+ """Returns streaming mode flag state"""
23
+ return self.__real_time_update
24
+
25
+ @property
26
+ def is_consent_required(self) -> bool:
27
+ """Returns consent required flag state"""
28
+ return self.__is_consent_required
@@ -15,5 +15,5 @@ class VariationByExposition:
15
15
 
16
16
  def __init__(self, dict_json: Dict[str, Any]):
17
17
  self.variation_key: str = dict_json.get("variationKey", "")
18
- self.variation_id: Optional[int] = dict_json.get("variationId", "")
19
- self.exposition: int = dict_json.get("exposition", "")
18
+ self.variation_id: Optional[int] = dict_json.get("variationId")
19
+ self.exposition: float = dict_json.get("exposition", 0.0)
kameleoon/data/browser.py CHANGED
@@ -3,7 +3,7 @@
3
3
  from enum import IntEnum
4
4
  from typing import Optional
5
5
  from kameleoon.data.data import Data, DataType
6
- from kameleoon.exceptions import KameleoonException
6
+ from kameleoon.network.sendable import DuplicationUnsafeSendableBase
7
7
  from kameleoon.network.query_builder import QueryBuilder, QueryParam, QueryParams
8
8
 
9
9
 
@@ -18,7 +18,7 @@ class BrowserType(IntEnum):
18
18
  OTHER: int = 5
19
19
 
20
20
 
21
- class Browser(Data):
21
+ class Browser(Data, DuplicationUnsafeSendableBase):
22
22
  """Browser data"""
23
23
 
24
24
  EVENT_TYPE = "staticData"
@@ -34,18 +34,27 @@ class Browser(Data):
34
34
  kameleoon_client.add_data(visitor_code, Browser(BrowserType.CHROME))
35
35
  """
36
36
  super().__init__()
37
- self.browser_type = browser_type
38
- self.version = version
39
- self._instance: DataType = DataType.BROWSER
40
-
41
- def obtain_full_post_text_line(self) -> str:
42
- if self.browser_type < 0:
43
- raise KameleoonException("Browser not recognized")
44
- query_builder = QueryBuilder(
37
+ self.__browser_type = browser_type
38
+ self.__version = version
39
+
40
+ @property
41
+ def browser_type(self) -> BrowserType:
42
+ """Returns browser type"""
43
+ return self.__browser_type
44
+
45
+ @property
46
+ def version(self) -> Optional[float]:
47
+ """Returns version"""
48
+ return self.__version
49
+
50
+ @property
51
+ def data_type(self) -> DataType:
52
+ return DataType.BROWSER
53
+
54
+ def _add_query_params(self, qb: QueryBuilder) -> None:
55
+ qb.extend(
45
56
  QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE),
46
57
  QueryParam(QueryParams.BROWSER_INDEX, str(self.browser_type.value)),
47
- QueryParam(QueryParams.NONCE, self._nonce),
48
58
  )
49
59
  if self.version:
50
- query_builder.append(QueryParam(QueryParams.BROWSER_VERSION, str(self.version)))
51
- return str(query_builder)
60
+ qb.append(QueryParam(QueryParams.BROWSER_VERSION, str(self.version)))
@@ -1,11 +1,12 @@
1
1
  # pylint: disable=duplicate-code
2
2
  """Conversion data"""
3
3
  from kameleoon.data.data import Data, DataType
4
+ from kameleoon.network.sendable import DuplicationSafeSendableBase
4
5
  from kameleoon.network.query_builder import QueryBuilder, QueryParam, QueryParams
5
6
 
6
7
 
7
8
  # pylint: disable=R0801
8
- class Conversion(Data):
9
+ class Conversion(Data, DuplicationSafeSendableBase):
9
10
  """Conversion is used for tracking visitors conversions"""
10
11
 
11
12
  EVENT_TYPE = "conversion"
@@ -27,19 +28,35 @@ class Conversion(Data):
27
28
 
28
29
  """
29
30
  super().__init__()
30
- self.goal_id = goal_id
31
- self.revenue = revenue
32
- self.negative = negative
33
- self._instance: DataType = DataType.CONVERSION
34
-
35
- def obtain_full_post_text_line(self) -> str:
31
+ self.__goal_id = goal_id
32
+ self.__revenue = revenue
33
+ self.__negative = negative
34
+
35
+ @property
36
+ def goal_id(self) -> int:
37
+ """Returns goal ID"""
38
+ return self.__goal_id
39
+
40
+ @property
41
+ def revenue(self) -> float:
42
+ """Returns revenue"""
43
+ return self.__revenue
44
+
45
+ @property
46
+ def negative(self) -> bool:
47
+ """Returns negative flag state"""
48
+ return self.__negative
49
+
50
+ @property
51
+ def data_type(self) -> DataType:
52
+ return DataType.CONVERSION
53
+
54
+ def _add_query_params(self, qb: QueryBuilder) -> None:
36
55
  # remove query_builder, it's done due due pylint issue with R0801 - duplicate_code,
37
56
  # need to update pylint and return str(QueryBuilder) straightaway
38
- query_builder = QueryBuilder(
57
+ qb.extend(
39
58
  QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE),
40
59
  QueryParam(QueryParams.GOAL_ID, str(self.goal_id)),
41
60
  QueryParam(QueryParams.REVENUE, str(self.revenue)),
42
61
  QueryParam(QueryParams.NEGATIVE, "true" if self.negative else "false"),
43
- QueryParam(QueryParams.NONCE, self._nonce),
44
62
  )
45
- return str(query_builder)
@@ -1,30 +1,23 @@
1
1
  """Custom data"""
2
2
 
3
3
  import json
4
- from typing import Optional, Tuple
5
- import warnings
4
+ from typing import Tuple
6
5
  from kameleoon.data.data import Data, DataType
6
+ from kameleoon.network.sendable import DuplicationUnsafeSendableBase
7
7
  from kameleoon.network.query_builder import QueryBuilder, QueryParam, QueryParams
8
8
 
9
9
 
10
- class CustomData(Data):
10
+ class CustomData(Data, DuplicationUnsafeSendableBase):
11
11
  """Custom data"""
12
12
 
13
13
  EVENT_TYPE = "customData"
14
14
 
15
- @property
16
- def values(self) -> Tuple[str, ...]:
17
- """Stored values."""
18
- return self.__values
19
-
20
- def __init__(self, id: int, *args: str, value: Optional[str] = None) -> None:
15
+ def __init__(self, id: int, *args: str) -> None:
21
16
  """
22
17
  :param id: Index / ID of the custom data to be stored. This field is mandatory.
23
18
  :type id: int
24
19
  :param `*args`: Values of the custom data to be stored. This field is optional.
25
- :type `*args`: Tuple[str, ...]
26
- :param value: Single value of the custom data to be stored. This field is optional.
27
- :type value: Optional[str]
20
+ :type `*args`: str
28
21
 
29
22
  Example:
30
23
 
@@ -34,27 +27,32 @@ class CustomData(Data):
34
27
  """
35
28
  # pylint: disable=invalid-name,redefined-builtin
36
29
  super().__init__()
37
- self.id = str(id)
38
- if value is None:
39
- self.__values = args
40
- else:
41
- self.__values = (*args, value)
42
- warnings.warn(
43
- "Passing deprecated parameter `value`. Please pass variadic parameter list instead.",
44
- category=DeprecationWarning,
45
- )
46
- self._instance: DataType = DataType.CUSTOM_DATA
47
-
48
- def obtain_full_post_text_line(self) -> str:
49
- if len(self.__values) == 0:
50
- return ""
30
+ # pylint: disable=W0511
31
+ self.__id = id
32
+ self.__values = args
33
+
34
+ @property
35
+ def id(self) -> int: # pylint: disable=C0103
36
+ """Returns ID"""
37
+ return self.__id
38
+
39
+ @property
40
+ def values(self) -> Tuple[str, ...]:
41
+ """Stored values."""
42
+ return self.__values
43
+
44
+ @property
45
+ def data_type(self) -> DataType:
46
+ return DataType.CUSTOM_DATA
47
+
48
+ def encode_query(self) -> str:
49
+ return super().encode_query() if len(self.__values) > 0 else ""
50
+
51
+ def _add_query_params(self, qb: QueryBuilder) -> None:
51
52
  str_values = json.dumps({v: 1 for v in self.__values}, separators=(",", ":"))
52
- return str(
53
- QueryBuilder(
54
- QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE),
55
- QueryParam(QueryParams.INDEX, self.id),
56
- QueryParam(QueryParams.VALUES_COUNT_MAP, str_values),
57
- QueryParam(QueryParams.OVERWRITE, "true"),
58
- QueryParam(QueryParams.NONCE, self._nonce),
59
- )
53
+ qb.extend(
54
+ QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE),
55
+ QueryParam(QueryParams.INDEX, str(self.id)),
56
+ QueryParam(QueryParams.VALUES_COUNT_MAP, str_values),
57
+ QueryParam(QueryParams.OVERWRITE, "true"),
60
58
  )
kameleoon/data/data.py CHANGED
@@ -1,8 +1,6 @@
1
1
  """ Kameleoon data module"""
2
2
  from enum import IntEnum
3
- from typing import Any
4
-
5
- from kameleoon.network.post_body_line import PostBodyLine, get_nonce
3
+ from typing import Any, Dict
6
4
 
7
5
 
8
6
  class DataType(IntEnum):
@@ -13,23 +11,22 @@ class DataType(IntEnum):
13
11
  CONVERSION = 2
14
12
  DEVICE = 3
15
13
  PAGE_VIEW = 4
14
+ USER_AGENT = 5
15
+ ASSIGNED_VARIATION = 6
16
16
 
17
17
 
18
- class Data(PostBodyLine):
18
+ class BaseData:
19
19
  """Base data class"""
20
20
 
21
- def __init__(self) -> None:
22
- super().__init__()
23
- self._nonce: str = get_nonce()
24
- self.sent: bool = False
21
+ @property
22
+ def data_type(self) -> DataType:
23
+ """Returns data type of the instance"""
24
+ raise NotImplementedError
25
25
 
26
- def to_dict(self) -> dict[str, Any]:
26
+ def to_dict(self) -> Dict[str, Any]:
27
27
  """Convert class instance to dict"""
28
28
  return self.__dict__
29
29
 
30
- def obtain_full_post_text_line(self) -> str:
31
- """
32
- obtain full post text line
33
- :return:
34
- """
35
- raise NotImplementedError
30
+
31
+ class Data(BaseData): # pylint: disable=W0223
32
+ """Base external data class"""
kameleoon/data/device.py CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  from enum import Enum
5
5
  from kameleoon.data.data import Data, DataType
6
+ from kameleoon.network.sendable import DuplicationUnsafeSendableBase
6
7
  from kameleoon.network.query_builder import QueryBuilder, QueryParam, QueryParams
7
8
 
8
9
 
@@ -14,7 +15,7 @@ class DeviceType(Enum):
14
15
  DESKTOP: str = "DESKTOP"
15
16
 
16
17
 
17
- class Device(Data):
18
+ class Device(Data, DuplicationUnsafeSendableBase):
18
19
  """Device data"""
19
20
 
20
21
  EVENT_TYPE = "staticData"
@@ -28,14 +29,19 @@ class Device(Data):
28
29
  kameleoon_client.add_data(visitor_code, Device(DeviceType.PHONE))
29
30
  """
30
31
  super().__init__()
31
- self.device_type = device_type
32
- self._instance: DataType = DataType.DEVICE
33
-
34
- def obtain_full_post_text_line(self) -> str:
35
- return str(
36
- QueryBuilder(
37
- QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE),
38
- QueryParam(QueryParams.DEVICE_TYPE, self.device_type.value),
39
- QueryParam(QueryParams.NONCE, self._nonce),
40
- )
32
+ self.__device_type = device_type
33
+
34
+ @property
35
+ def device_type(self) -> DeviceType:
36
+ """Returns device type"""
37
+ return self.__device_type
38
+
39
+ @property
40
+ def data_type(self) -> DataType:
41
+ return DataType.DEVICE
42
+
43
+ def _add_query_params(self, qb: QueryBuilder) -> None:
44
+ qb.extend(
45
+ QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE),
46
+ QueryParam(QueryParams.DEVICE_TYPE, self.device_type.value),
41
47
  )
@@ -3,10 +3,11 @@
3
3
  import json
4
4
  from typing import List, Optional
5
5
  from kameleoon.data.data import Data, DataType
6
+ from kameleoon.network.sendable import DuplicationSafeSendableBase
6
7
  from kameleoon.network.query_builder import QueryBuilder, QueryParam, QueryParams
7
8
 
8
9
 
9
- class PageView(Data):
10
+ class PageView(Data, DuplicationSafeSendableBase):
10
11
  """Page view"""
11
12
 
12
13
  EVENT_TYPE = "page"
@@ -27,19 +28,38 @@ class PageView(Data):
27
28
  kameleoon_client.add_data(visitor_code, PageView("www.test.com", "test-title"))
28
29
  """
29
30
  super().__init__()
30
- self.url = url
31
- self.title = title
32
- self.referrers = referrers
33
- self._instance: DataType = DataType.PAGE_VIEW
31
+ self.__url = url
32
+ self.__title = title
33
+ self.__referrers = referrers
34
34
 
35
- def obtain_full_post_text_line(self) -> str:
36
- qb = QueryBuilder( # pylint: disable=C0103
35
+ @property
36
+ def url(self) -> str:
37
+ """Returns URL"""
38
+ return self.__url
39
+
40
+ @property
41
+ def title(self) -> str:
42
+ """Returns title"""
43
+ return self.__title
44
+
45
+ @property
46
+ def referrers(self) -> Optional[List[int]]:
47
+ """Returns referrer list"""
48
+ return self.__referrers
49
+
50
+ @property
51
+ def data_type(self) -> DataType:
52
+ return DataType.PAGE_VIEW
53
+
54
+ def encode_query(self) -> str:
55
+ return super().encode_query() if len(self.__url) > 0 else ""
56
+
57
+ def _add_query_params(self, qb: QueryBuilder) -> None:
58
+ qb.extend(
37
59
  QueryParam(QueryParams.EVENT_TYPE, self.EVENT_TYPE),
38
60
  QueryParam(QueryParams.HREF, self.url),
39
61
  QueryParam(QueryParams.TITLE, self.title),
40
- QueryParam(QueryParams.NONCE, self._nonce),
41
62
  )
42
63
  if self.referrers:
43
64
  str_referrers = json.dumps(self.referrers, separators=(",", ":"))
44
65
  qb.append(QueryParam(QueryParams.REFERRERS_INDICES, str_referrers))
45
- return str(qb)
@@ -1,6 +1,6 @@
1
1
  """User Agent data"""
2
2
 
3
- from kameleoon.data.data import Data
3
+ from kameleoon.data.data import Data, DataType
4
4
 
5
5
 
6
6
  # pylint: disable=W0223,W0231
@@ -15,11 +15,17 @@ class UserAgent(Data):
15
15
  .. code-block:: python3
16
16
  kameleoon_client.add_data(visitor_code, UserAgent('TestUserAgent'))
17
17
  """
18
- self.value = value
18
+ super().__init__()
19
+ self.__value = value
19
20
 
20
- def get_value(self) -> str:
21
+ @property
22
+ def value(self) -> str:
21
23
  """
22
24
  return user agent value
23
25
  :return:
24
26
  """
25
- return self.value
27
+ return self.__value
28
+
29
+ @property
30
+ def data_type(self) -> DataType:
31
+ return DataType.USER_AGENT
kameleoon/defaults.py CHANGED
@@ -4,38 +4,6 @@ import os
4
4
 
5
5
  BASE_DIR: str = os.path.dirname((os.path.dirname(__file__)))
6
6
 
7
- DEFAULT_CONFIGURATION_PATH: str = os.path.join(
8
- "/etc", "kameleoon", "client-python.yaml"
9
- )
10
-
11
7
  DEBUG: bool = True
12
8
 
13
- DEFAULT_TIMEOUT_MILLISECONDS: int = 5000 # milli-seconds
14
9
  MILLISECONDS_IN_SECOND: int = 1000
15
- DEFAULT_TIMEOUT_SECONDS: float = (
16
- DEFAULT_TIMEOUT_MILLISECONDS / MILLISECONDS_IN_SECOND
17
- ) # seconds
18
-
19
- DEFAULT_MILLISECONDS_BETWEEN_TARGETING_DATA_UPDATE: int = 1800000
20
-
21
- MINUTES_SESSION_DURATION: int = 30
22
-
23
- TARGETING_DATA_MAXIMUM_SIZE_BYTES = 500
24
-
25
- DEFAULT_VISITOR_DATA_MAXIMUM_SIZE = 500 # Mb
26
-
27
- KAMELEOON_COOKIE_NAME = "kameleoonVisitorCode"
28
-
29
- EXPIRE_DAYS = 380
30
-
31
- MAX_AGE = 32832000
32
-
33
- USER_AGENT_MAX_COUNT = 100_000
34
-
35
- KAMELEOON_COOKIE_VALUE_LENGTH = 16
36
-
37
- KAMELEOON_VISITOR_CODE_LENGTH = 255
38
-
39
- DEFAULT_CONFIGURATION_UPDATE_INTERVAL = 60 * 60 # sec
40
-
41
- KAMELEOON_KEY_JS_COOKIE = "_js_"