trodo-python 1.0.0__py3-none-any.whl → 1.2.0__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.
@@ -1,106 +1,106 @@
1
- """Group management methods and GroupProfile proxy."""
2
-
3
- from __future__ import annotations
4
-
5
- from typing import Any, Callable, Dict, List, Optional, Union
6
-
7
- from ..api import endpoints
8
- from ..types import ApiResult
9
-
10
-
11
- class GroupProfile:
12
- def __init__(
13
- self,
14
- http_client: object,
15
- site_id: str,
16
- distinct_id: str,
17
- group_key: str,
18
- group_id: str,
19
- ) -> None:
20
- self._http = http_client
21
- self._site_id = site_id
22
- self._distinct_id = distinct_id
23
- self._group_key = group_key
24
- self._group_id = group_id
25
-
26
- def _base(self) -> Dict[str, Any]:
27
- return {
28
- "siteId": self._site_id,
29
- "userId": self._distinct_id,
30
- "groupKey": self._group_key,
31
- "groupId": self._group_id,
32
- }
33
-
34
- def _call(self, method: str, extra: Optional[Dict[str, Any]] = None) -> ApiResult:
35
- payload = {**self._base(), **(extra or {})}
36
- return self._http.post_group( # type: ignore[attr-defined]
37
- f"{endpoints.GROUPS_PROFILE}/{method}", payload
38
- )
39
-
40
- def set(self, properties: Dict[str, Any]) -> ApiResult:
41
- return self._call("set", {"properties": properties})
42
-
43
- def set_once(self, properties: Dict[str, Any]) -> ApiResult:
44
- return self._call("set_once", {"properties": properties})
45
-
46
- def union(self, list_name: str, values: List[Any]) -> ApiResult:
47
- return self._call("union", {"listName": list_name, "values": values})
48
-
49
- def remove(self, list_name: str, value: Any) -> ApiResult:
50
- return self._call("remove", {"listName": list_name, "value": value})
51
-
52
- def unset(self, property: str) -> ApiResult:
53
- return self._call("unset", {"property": property})
54
-
55
- def increment(self, property: str, value: float = 1) -> ApiResult:
56
- return self._call("increment", {"property": property, "value": value})
57
-
58
- def append(self, property: str, value: Any) -> ApiResult:
59
- return self._call("append", {"property": property, "value": value})
60
-
61
- def delete(self) -> ApiResult:
62
- return self._call("delete")
63
-
64
-
65
- class GroupManager:
66
- def __init__(
67
- self,
68
- http_client: object,
69
- site_id: str,
70
- get_distinct_id: Callable[[], str],
71
- ) -> None:
72
- self._http = http_client
73
- self._site_id = site_id
74
- self._get_distinct_id = get_distinct_id
75
-
76
- def _base(self) -> Dict[str, Any]:
77
- return {"siteId": self._site_id, "userId": self._get_distinct_id()}
78
-
79
- def set_group(
80
- self, group_key: str, group_id: Union[str, List[str]]
81
- ) -> ApiResult:
82
- return self._http.post_group( # type: ignore[attr-defined]
83
- endpoints.GROUPS_SET,
84
- {**self._base(), "groupKey": group_key, "groupId": group_id},
85
- )
86
-
87
- def add_group(self, group_key: str, group_id: str) -> ApiResult:
88
- return self._http.post_group( # type: ignore[attr-defined]
89
- endpoints.GROUPS_ADD,
90
- {**self._base(), "groupKey": group_key, "groupId": group_id},
91
- )
92
-
93
- def remove_group(self, group_key: str, group_id: str) -> ApiResult:
94
- return self._http.post_group( # type: ignore[attr-defined]
95
- endpoints.GROUPS_REMOVE,
96
- {**self._base(), "groupKey": group_key, "groupId": group_id},
97
- )
98
-
99
- def get_group(self, group_key: str, group_id: str) -> GroupProfile:
100
- return GroupProfile(
101
- self._http,
102
- self._site_id,
103
- self._get_distinct_id(),
104
- group_key,
105
- group_id,
106
- )
1
+ """Group management methods and GroupProfile proxy."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Callable, Dict, List, Optional, Union
6
+
7
+ from ..api import endpoints
8
+ from ..types import ApiResult
9
+
10
+
11
+ class GroupProfile:
12
+ def __init__(
13
+ self,
14
+ http_client: object,
15
+ site_id: str,
16
+ distinct_id: str,
17
+ group_key: str,
18
+ group_id: str,
19
+ ) -> None:
20
+ self._http = http_client
21
+ self._site_id = site_id
22
+ self._distinct_id = distinct_id
23
+ self._group_key = group_key
24
+ self._group_id = group_id
25
+
26
+ def _base(self) -> Dict[str, Any]:
27
+ return {
28
+ "siteId": self._site_id,
29
+ "userId": self._distinct_id,
30
+ "groupKey": self._group_key,
31
+ "groupId": self._group_id,
32
+ }
33
+
34
+ def _call(self, method: str, extra: Optional[Dict[str, Any]] = None) -> ApiResult:
35
+ payload = {**self._base(), **(extra or {})}
36
+ return self._http.post_group( # type: ignore[attr-defined]
37
+ f"{endpoints.GROUPS_PROFILE}/{method}", payload
38
+ )
39
+
40
+ def set(self, properties: Dict[str, Any]) -> ApiResult:
41
+ return self._call("set", {"properties": properties})
42
+
43
+ def set_once(self, properties: Dict[str, Any]) -> ApiResult:
44
+ return self._call("set_once", {"properties": properties})
45
+
46
+ def union(self, list_name: str, values: List[Any]) -> ApiResult:
47
+ return self._call("union", {"listName": list_name, "values": values})
48
+
49
+ def remove(self, list_name: str, value: Any) -> ApiResult:
50
+ return self._call("remove", {"listName": list_name, "value": value})
51
+
52
+ def unset(self, property: str) -> ApiResult:
53
+ return self._call("unset", {"property": property})
54
+
55
+ def increment(self, property: str, value: float = 1) -> ApiResult:
56
+ return self._call("increment", {"property": property, "value": value})
57
+
58
+ def append(self, property: str, value: Any) -> ApiResult:
59
+ return self._call("append", {"property": property, "value": value})
60
+
61
+ def delete(self) -> ApiResult:
62
+ return self._call("delete")
63
+
64
+
65
+ class GroupManager:
66
+ def __init__(
67
+ self,
68
+ http_client: object,
69
+ site_id: str,
70
+ get_distinct_id: Callable[[], str],
71
+ ) -> None:
72
+ self._http = http_client
73
+ self._site_id = site_id
74
+ self._get_distinct_id = get_distinct_id
75
+
76
+ def _base(self) -> Dict[str, Any]:
77
+ return {"siteId": self._site_id, "userId": self._get_distinct_id()}
78
+
79
+ def set_group(
80
+ self, group_key: str, group_id: Union[str, List[str]]
81
+ ) -> ApiResult:
82
+ return self._http.post_group( # type: ignore[attr-defined]
83
+ endpoints.GROUPS_SET,
84
+ {**self._base(), "groupKey": group_key, "groupId": group_id},
85
+ )
86
+
87
+ def add_group(self, group_key: str, group_id: str) -> ApiResult:
88
+ return self._http.post_group( # type: ignore[attr-defined]
89
+ endpoints.GROUPS_ADD,
90
+ {**self._base(), "groupKey": group_key, "groupId": group_id},
91
+ )
92
+
93
+ def remove_group(self, group_key: str, group_id: str) -> ApiResult:
94
+ return self._http.post_group( # type: ignore[attr-defined]
95
+ endpoints.GROUPS_REMOVE,
96
+ {**self._base(), "groupKey": group_key, "groupId": group_id},
97
+ )
98
+
99
+ def get_group(self, group_key: str, group_id: str) -> GroupProfile:
100
+ return GroupProfile(
101
+ self._http,
102
+ self._site_id,
103
+ self._get_distinct_id(),
104
+ group_key,
105
+ group_id,
106
+ )
@@ -1,77 +1,77 @@
1
- """People (user profile) methods."""
2
-
3
- from __future__ import annotations
4
-
5
- from typing import Any, Callable, Dict, List, Optional, Union
6
-
7
- from ..api import endpoints
8
- from ..types import ApiResult
9
-
10
-
11
- class PeopleManager:
12
- def __init__(
13
- self,
14
- http_client: object,
15
- site_id: str,
16
- get_distinct_id: Callable[[], str],
17
- ) -> None:
18
- self._http = http_client
19
- self._site_id = site_id
20
- self._get_distinct_id = get_distinct_id
21
-
22
- def _base(self) -> Dict[str, Any]:
23
- return {"siteId": self._site_id, "userId": self._get_distinct_id()}
24
-
25
- def set(self, properties: Dict[str, Any]) -> ApiResult:
26
- return self._http.post_people( # type: ignore[attr-defined]
27
- endpoints.PEOPLE_SET, {**self._base(), "properties": properties}
28
- )
29
-
30
- def set_once(self, properties: Dict[str, Any]) -> ApiResult:
31
- return self._http.post_people( # type: ignore[attr-defined]
32
- endpoints.PEOPLE_SET_ONCE, {**self._base(), "properties": properties}
33
- )
34
-
35
- def unset(self, keys: Union[str, List[str]]) -> ApiResult:
36
- k = [keys] if isinstance(keys, str) else keys
37
- return self._http.post_people( # type: ignore[attr-defined]
38
- endpoints.PEOPLE_UNSET, {**self._base(), "keys": k}
39
- )
40
-
41
- def increment(self, key: str, amount: float = 1) -> ApiResult:
42
- return self._http.post_people( # type: ignore[attr-defined]
43
- endpoints.PEOPLE_INCREMENT, {**self._base(), "key": key, "amount": amount}
44
- )
45
-
46
- def append(self, key: str, values: List[Any]) -> ApiResult:
47
- return self._http.post_people( # type: ignore[attr-defined]
48
- endpoints.PEOPLE_APPEND, {**self._base(), "key": key, "values": values}
49
- )
50
-
51
- def union(self, key: str, values: List[Any]) -> ApiResult:
52
- return self._http.post_people( # type: ignore[attr-defined]
53
- endpoints.PEOPLE_UNION, {**self._base(), "key": key, "values": values}
54
- )
55
-
56
- def remove(self, key: str, values: List[Any]) -> ApiResult:
57
- return self._http.post_people( # type: ignore[attr-defined]
58
- endpoints.PEOPLE_REMOVE, {**self._base(), "key": key, "values": values}
59
- )
60
-
61
- def track_charge(
62
- self, amount: float, properties: Optional[Dict[str, Any]] = None
63
- ) -> ApiResult:
64
- return self._http.post_people( # type: ignore[attr-defined]
65
- endpoints.PEOPLE_TRACK_CHARGE,
66
- {**self._base(), "amount": amount, "properties": properties or {}},
67
- )
68
-
69
- def clear_charges(self) -> ApiResult:
70
- return self._http.post_people( # type: ignore[attr-defined]
71
- endpoints.PEOPLE_CLEAR_CHARGES, self._base()
72
- )
73
-
74
- def delete_user(self) -> ApiResult:
75
- return self._http.post_people( # type: ignore[attr-defined]
76
- endpoints.PEOPLE_DELETE_USER, self._base()
77
- )
1
+ """People (user profile) methods."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Callable, Dict, List, Optional, Union
6
+
7
+ from ..api import endpoints
8
+ from ..types import ApiResult
9
+
10
+
11
+ class PeopleManager:
12
+ def __init__(
13
+ self,
14
+ http_client: object,
15
+ site_id: str,
16
+ get_distinct_id: Callable[[], str],
17
+ ) -> None:
18
+ self._http = http_client
19
+ self._site_id = site_id
20
+ self._get_distinct_id = get_distinct_id
21
+
22
+ def _base(self) -> Dict[str, Any]:
23
+ return {"siteId": self._site_id, "userId": self._get_distinct_id()}
24
+
25
+ def set(self, properties: Dict[str, Any]) -> ApiResult:
26
+ return self._http.post_people( # type: ignore[attr-defined]
27
+ endpoints.PEOPLE_SET, {**self._base(), "properties": properties}
28
+ )
29
+
30
+ def set_once(self, properties: Dict[str, Any]) -> ApiResult:
31
+ return self._http.post_people( # type: ignore[attr-defined]
32
+ endpoints.PEOPLE_SET_ONCE, {**self._base(), "properties": properties}
33
+ )
34
+
35
+ def unset(self, keys: Union[str, List[str]]) -> ApiResult:
36
+ k = [keys] if isinstance(keys, str) else keys
37
+ return self._http.post_people( # type: ignore[attr-defined]
38
+ endpoints.PEOPLE_UNSET, {**self._base(), "keys": k}
39
+ )
40
+
41
+ def increment(self, key: str, amount: float = 1) -> ApiResult:
42
+ return self._http.post_people( # type: ignore[attr-defined]
43
+ endpoints.PEOPLE_INCREMENT, {**self._base(), "key": key, "amount": amount}
44
+ )
45
+
46
+ def append(self, key: str, values: List[Any]) -> ApiResult:
47
+ return self._http.post_people( # type: ignore[attr-defined]
48
+ endpoints.PEOPLE_APPEND, {**self._base(), "key": key, "values": values}
49
+ )
50
+
51
+ def union(self, key: str, values: List[Any]) -> ApiResult:
52
+ return self._http.post_people( # type: ignore[attr-defined]
53
+ endpoints.PEOPLE_UNION, {**self._base(), "key": key, "values": values}
54
+ )
55
+
56
+ def remove(self, key: str, values: List[Any]) -> ApiResult:
57
+ return self._http.post_people( # type: ignore[attr-defined]
58
+ endpoints.PEOPLE_REMOVE, {**self._base(), "key": key, "values": values}
59
+ )
60
+
61
+ def track_charge(
62
+ self, amount: float, properties: Optional[Dict[str, Any]] = None
63
+ ) -> ApiResult:
64
+ return self._http.post_people( # type: ignore[attr-defined]
65
+ endpoints.PEOPLE_TRACK_CHARGE,
66
+ {**self._base(), "amount": amount, "properties": properties or {}},
67
+ )
68
+
69
+ def clear_charges(self) -> ApiResult:
70
+ return self._http.post_people( # type: ignore[attr-defined]
71
+ endpoints.PEOPLE_CLEAR_CHARGES, self._base()
72
+ )
73
+
74
+ def delete_user(self) -> ApiResult:
75
+ return self._http.post_people( # type: ignore[attr-defined]
76
+ endpoints.PEOPLE_DELETE_USER, self._base()
77
+ )
@@ -1,52 +1,52 @@
1
- """Background timer-based batch flusher."""
2
-
3
- from __future__ import annotations
4
-
5
- import threading
6
- from typing import Optional
7
-
8
- from .event_queue import EventQueue
9
-
10
-
11
- class BatchFlusher:
12
- def __init__(
13
- self,
14
- queue: EventQueue,
15
- http_client: object,
16
- flush_interval: float,
17
- ) -> None:
18
- self._queue = queue
19
- self._http = http_client
20
- self._flush_interval = flush_interval
21
- self._timer: Optional[threading.Timer] = None
22
- self._lock = threading.Lock()
23
-
24
- def start(self) -> None:
25
- self._reschedule()
26
-
27
- def stop(self) -> None:
28
- with self._lock:
29
- if self._timer:
30
- self._timer.cancel()
31
- self._timer = None
32
-
33
- def flush(self) -> None:
34
- events = self._queue.drain()
35
- if not events:
36
- return
37
- self._http.post_bulk_events(events) # type: ignore[attr-defined]
38
-
39
- def _reschedule(self) -> None:
40
- with self._lock:
41
- if self._timer:
42
- self._timer.cancel()
43
- t = threading.Timer(self._flush_interval, self._tick)
44
- t.daemon = True
45
- t.start()
46
- self._timer = t
47
-
48
- def _tick(self) -> None:
49
- try:
50
- self.flush()
51
- finally:
52
- self._reschedule()
1
+ """Background timer-based batch flusher."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import threading
6
+ from typing import Optional
7
+
8
+ from .event_queue import EventQueue
9
+
10
+
11
+ class BatchFlusher:
12
+ def __init__(
13
+ self,
14
+ queue: EventQueue,
15
+ http_client: object,
16
+ flush_interval: float,
17
+ ) -> None:
18
+ self._queue = queue
19
+ self._http = http_client
20
+ self._flush_interval = flush_interval
21
+ self._timer: Optional[threading.Timer] = None
22
+ self._lock = threading.Lock()
23
+
24
+ def start(self) -> None:
25
+ self._reschedule()
26
+
27
+ def stop(self) -> None:
28
+ with self._lock:
29
+ if self._timer:
30
+ self._timer.cancel()
31
+ self._timer = None
32
+
33
+ def flush(self) -> None:
34
+ events = self._queue.drain()
35
+ if not events:
36
+ return
37
+ self._http.post_bulk_events(events) # type: ignore[attr-defined]
38
+
39
+ def _reschedule(self) -> None:
40
+ with self._lock:
41
+ if self._timer:
42
+ self._timer.cancel()
43
+ t = threading.Timer(self._flush_interval, self._tick)
44
+ t.daemon = True
45
+ t.start()
46
+ self._timer = t
47
+
48
+ def _tick(self) -> None:
49
+ try:
50
+ self.flush()
51
+ finally:
52
+ self._reschedule()
@@ -1,32 +1,32 @@
1
- """Thread-safe in-memory event queue."""
2
-
3
- from __future__ import annotations
4
-
5
- import threading
6
- from typing import List
7
-
8
- from ..types import EventPayload
9
-
10
-
11
- class EventQueue:
12
- def __init__(self, max_size: int = 500) -> None:
13
- self._max_size = max_size
14
- self._queue: List[EventPayload] = []
15
- self._lock = threading.Lock()
16
-
17
- def enqueue(self, event: EventPayload) -> bool:
18
- """Returns True if flush threshold reached."""
19
- with self._lock:
20
- self._queue.append(event)
21
- return len(self._queue) >= self._max_size
22
-
23
- def drain(self) -> List[EventPayload]:
24
- """Atomically take all queued events."""
25
- with self._lock:
26
- events = list(self._queue)
27
- self._queue.clear()
28
- return events
29
-
30
- def size(self) -> int:
31
- with self._lock:
32
- return len(self._queue)
1
+ """Thread-safe in-memory event queue."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import threading
6
+ from typing import List
7
+
8
+ from ..types import EventPayload
9
+
10
+
11
+ class EventQueue:
12
+ def __init__(self, max_size: int = 500) -> None:
13
+ self._max_size = max_size
14
+ self._queue: List[EventPayload] = []
15
+ self._lock = threading.Lock()
16
+
17
+ def enqueue(self, event: EventPayload) -> bool:
18
+ """Returns True if flush threshold reached."""
19
+ with self._lock:
20
+ self._queue.append(event)
21
+ return len(self._queue) >= self._max_size
22
+
23
+ def drain(self) -> List[EventPayload]:
24
+ """Atomically take all queued events."""
25
+ with self._lock:
26
+ events = list(self._queue)
27
+ self._queue.clear()
28
+ return events
29
+
30
+ def size(self) -> int:
31
+ with self._lock:
32
+ return len(self._queue)