posthoganalytics 6.0.4__py3-none-any.whl → 6.1.1__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.
@@ -20,22 +20,105 @@ __version__ = VERSION
20
20
 
21
21
 
22
22
  def new_context(fresh=False, capture_exceptions=True):
23
+ """
24
+ Create a new context scope that will be active for the duration of the with block.
25
+
26
+ Args:
27
+ fresh: Whether to start with a fresh context (default: False)
28
+ capture_exceptions: Whether to capture exceptions raised within the context (default: True)
29
+
30
+ Examples:
31
+ ```python
32
+ from posthoganalytics import new_context, tag, capture
33
+ with new_context():
34
+ tag("request_id", "123")
35
+ capture("event_name", properties={"property": "value"})
36
+ ```
37
+
38
+ Category:
39
+ Contexts
40
+ """
23
41
  return inner_new_context(fresh=fresh, capture_exceptions=capture_exceptions)
24
42
 
25
43
 
26
44
  def scoped(fresh=False, capture_exceptions=True):
45
+ """
46
+ Decorator that creates a new context for the function.
47
+
48
+ Args:
49
+ fresh: Whether to start with a fresh context (default: False)
50
+ capture_exceptions: Whether to capture and track exceptions with posthog error tracking (default: True)
51
+
52
+ Examples:
53
+ ```python
54
+ from posthoganalytics import scoped, tag, capture
55
+ @scoped()
56
+ def process_payment(payment_id):
57
+ tag("payment_id", payment_id)
58
+ capture("payment_started")
59
+ ```
60
+
61
+ Category:
62
+ Contexts
63
+ """
27
64
  return inner_scoped(fresh=fresh, capture_exceptions=capture_exceptions)
28
65
 
29
66
 
30
67
  def set_context_session(session_id: str):
68
+ """
69
+ Set the session ID for the current context.
70
+
71
+ Args:
72
+ session_id: The session ID to associate with the current context and its children
73
+
74
+ Examples:
75
+ ```python
76
+ from posthoganalytics import set_context_session
77
+ set_context_session("session_123")
78
+ ```
79
+
80
+ Category:
81
+ Contexts
82
+ """
31
83
  return inner_set_context_session(session_id)
32
84
 
33
85
 
34
86
  def identify_context(distinct_id: str):
87
+ """
88
+ Identify the current context with a distinct ID.
89
+
90
+ Args:
91
+ distinct_id: The distinct ID to associate with the current context and its children
92
+
93
+ Examples:
94
+ ```python
95
+ from posthoganalytics import identify_context
96
+ identify_context("user_123")
97
+ ```
98
+
99
+ Category:
100
+ Identification
101
+ """
35
102
  return inner_identify_context(distinct_id)
36
103
 
37
104
 
38
105
  def tag(name: str, value: Any):
106
+ """
107
+ Add a tag to the current context.
108
+
109
+ Args:
110
+ name: The tag key
111
+ value: The tag value
112
+
113
+ Examples:
114
+ ```python
115
+ from posthoganalytics import tag
116
+ tag("user_id", "123")
117
+ ```
118
+
119
+ Category:
120
+ Contexts
121
+ """
39
122
  return inner_tag(name, value)
40
123
 
41
124
 
@@ -60,6 +143,9 @@ log_captured_exceptions = False # type: bool
60
143
  project_root = None # type: Optional[str]
61
144
  # Used for our AI observability feature to not capture any prompt or output just usage + metadata
62
145
  privacy_mode = False # type: bool
146
+ # Whether to enable feature flag polling for local evaluation by default. Defaults to True.
147
+ # We recommend setting this to False if you are only using the personalApiKey for evaluating remote config payloads via `get_remote_config_payload` and not using local evaluation.
148
+ enable_local_evaluation = True # type: bool
63
149
 
64
150
  default_client = None # type: Optional[Client]
65
151
 
@@ -70,40 +156,62 @@ default_client = None # type: Optional[Client]
70
156
  # versions, without a breaking change, to get back the type information in function signatures
71
157
  def capture(event: str, **kwargs: Unpack[OptionalCaptureArgs]) -> Optional[str]:
72
158
  """
73
- Capture allows you to capture anything a user does within your system, which you can later use in PostHog to find patterns in usage, work out which features to improve or where people are giving up.
74
-
75
- A `capture` call requires
76
- - `event name` to specify the event
77
- - We recommend using [verb] [noun], like `movie played` or `movie updated` to easily identify what your events mean later on.
78
-
79
- Capture takes a number of optional arguments, which are defined by the `OptionalCaptureArgs` type.
80
-
81
- For example:
82
- ```python
83
- # Enter a new context (e.g. a request/response cycle, an instance of a background job, etc)
84
- with posthog.new_context():
85
- # Associate this context with some user, by distinct_id
86
- posthog.identify_context('some user')
87
-
88
- # Capture an event, associated with the context-level distinct ID ('some user')
89
- posthog.capture('movie started')
159
+ Capture anything a user does within your system.
90
160
 
91
- # Capture an event associated with some other user (overriding the context-level distinct ID)
92
- posthog.capture('movie joined', distinct_id='some-other-user')
93
-
94
- # Capture an event with some properties
95
- posthog.capture('movie played', properties={'movie_id': '123', 'category': 'romcom'})
96
-
97
- # Capture an event with some properties
98
- posthog.capture('purchase', properties={'product_id': '123', 'category': 'romcom'})
99
- # Capture an event with some associated group
100
- posthog.capture('purchase', groups={'company': 'id:5'})
101
-
102
- # Adding a tag to the current context will cause it to appear on all subsequent events
103
- posthog.tag_context('some-tag', 'some-value')
104
-
105
- posthog.capture('another-event') # Will be captured with `'some-tag': 'some-value'` in the properties dict
106
- ```
161
+ Args:
162
+ event: The event name to specify the event
163
+ **kwargs: Optional arguments including:
164
+ distinct_id: Unique identifier for the user
165
+ properties: Dict of event properties
166
+ timestamp: When the event occurred
167
+ groups: Dict of group types and IDs
168
+ disable_geoip: Whether to disable GeoIP lookup
169
+
170
+ Details:
171
+ Capture allows you to capture anything a user does within your system, which you can later use in PostHog to find patterns in usage, work out which features to improve or where people are giving up. A capture call requires an event name to specify the event. We recommend using [verb] [noun], like `movie played` or `movie updated` to easily identify what your events mean later on. Capture takes a number of optional arguments, which are defined by the `OptionalCaptureArgs` type.
172
+
173
+ Examples:
174
+ ```python
175
+ # Context and capture usage
176
+ from posthoganalytics import new_context, identify_context, tag_context, capture
177
+ # Enter a new context (e.g. a request/response cycle, an instance of a background job, etc)
178
+ with new_context():
179
+ # Associate this context with some user, by distinct_id
180
+ identify_context('some user')
181
+
182
+ # Capture an event, associated with the context-level distinct ID ('some user')
183
+ capture('movie started')
184
+
185
+ # Capture an event associated with some other user (overriding the context-level distinct ID)
186
+ capture('movie joined', distinct_id='some-other-user')
187
+
188
+ # Capture an event with some properties
189
+ capture('movie played', properties={'movie_id': '123', 'category': 'romcom'})
190
+
191
+ # Capture an event with some properties
192
+ capture('purchase', properties={'product_id': '123', 'category': 'romcom'})
193
+ # Capture an event with some associated group
194
+ capture('purchase', groups={'company': 'id:5'})
195
+
196
+ # Adding a tag to the current context will cause it to appear on all subsequent events
197
+ tag_context('some-tag', 'some-value')
198
+
199
+ capture('another-event') # Will be captured with `'some-tag': 'some-value'` in the properties dict
200
+ ```
201
+ ```python
202
+ # Set event properties
203
+ from posthoganalytics import capture
204
+ capture(
205
+ "user_signed_up",
206
+ distinct_id="distinct_id_of_the_user",
207
+ properties={
208
+ "login_type": "email",
209
+ "is_free_trial": "true"
210
+ }
211
+ )
212
+ ```
213
+ Category:
214
+ Events
107
215
  """
108
216
 
109
217
  return _proxy("capture", event, **kwargs)
@@ -112,21 +220,25 @@ def capture(event: str, **kwargs: Unpack[OptionalCaptureArgs]) -> Optional[str]:
112
220
  def set(**kwargs: Unpack[OptionalSetArgs]) -> Optional[str]:
113
221
  """
114
222
  Set properties on a user record.
115
- This will overwrite previous people property values. Generally operates similar to `capture`, with
116
- distinct_id being an optional argument, defaulting to the current context's distinct ID.
117
-
118
- If there is no context-level distinct ID, and no override distinct_id is passed, this function
119
- will do nothing.
120
-
121
- Context tags are folded into $set properties, so tagging the current context and then calling `set` will
122
- cause those tags to be set on the user (unlike capture, which causes them to just be set on the event).
123
223
 
124
- For example:
125
- ```python
126
- posthog.set(distinct_id='distinct id', properties={
127
- 'current_browser': 'Chrome',
128
- })
129
- ```
224
+ Details:
225
+ This will overwrite previous people property values. Generally operates similar to `capture`, with distinct_id being an optional argument, defaulting to the current context's distinct ID. If there is no context-level distinct ID, and no override distinct_id is passed, this function will do nothing. Context tags are folded into $set properties, so tagging the current context and then calling `set` will cause those tags to be set on the user (unlike capture, which causes them to just be set on the event).
226
+
227
+ Examples:
228
+ ```python
229
+ # Set person properties
230
+ from posthoganalytics import capture
231
+ capture(
232
+ 'distinct_id',
233
+ event='event_name',
234
+ properties={
235
+ '$set': {'name': 'Max Hedgehog'},
236
+ '$set_once': {'initial_url': '/blog'}
237
+ }
238
+ )
239
+ ```
240
+ Category:
241
+ Identification
130
242
  """
131
243
 
132
244
  return _proxy("set", **kwargs)
@@ -135,10 +247,26 @@ def set(**kwargs: Unpack[OptionalSetArgs]) -> Optional[str]:
135
247
  def set_once(**kwargs: Unpack[OptionalSetArgs]) -> Optional[str]:
136
248
  """
137
249
  Set properties on a user record, only if they do not yet exist.
138
- This will not overwrite previous people property values, unlike `set`.
139
250
 
140
- Otherwise, operates in an identical manner to `set`.
141
- ```
251
+ Details:
252
+ This will not overwrite previous people property values, unlike `set`. Otherwise, operates in an identical manner to `set`.
253
+
254
+ Examples:
255
+ ```python
256
+ # Set property once
257
+ from posthoganalytics import capture
258
+ capture(
259
+ 'distinct_id',
260
+ event='event_name',
261
+ properties={
262
+ '$set': {'name': 'Max Hedgehog'},
263
+ '$set_once': {'initial_url': '/blog'}
264
+ }
265
+ )
266
+
267
+ ```
268
+ Category:
269
+ Identification
142
270
  """
143
271
  return _proxy("set_once", **kwargs)
144
272
 
@@ -153,18 +281,27 @@ def group_identify(
153
281
  ):
154
282
  # type: (...) -> Optional[str]
155
283
  """
156
- Set properties on a group
157
-
158
- A `group_identify` call requires
159
- - `group_type` type of your group
160
- - `group_key` unique identifier of the group
284
+ Set properties on a group.
161
285
 
162
- For example:
163
- ```python
164
- posthog.group_identify('company', 5, {
165
- 'employees': 11,
166
- })
167
- ```
286
+ Args:
287
+ group_type: Type of your group
288
+ group_key: Unique identifier of the group
289
+ properties: Properties to set on the group
290
+ timestamp: Optional timestamp for the event
291
+ uuid: Optional UUID for the event
292
+ disable_geoip: Whether to disable GeoIP lookup
293
+
294
+ Examples:
295
+ ```python
296
+ # Group identify
297
+ from posthoganalytics import group_identify
298
+ group_identify('company', 'company_id_in_your_db', {
299
+ 'name': 'Awesome Inc.',
300
+ 'employees': 11
301
+ })
302
+ ```
303
+ Category:
304
+ Identification
168
305
  """
169
306
 
170
307
  return _proxy(
@@ -187,19 +324,26 @@ def alias(
187
324
  ):
188
325
  # type: (...) -> Optional[str]
189
326
  """
190
- To marry up whatever a user does before they sign up or log in with what they do after you need to make an alias call.
191
- This will allow you to answer questions like "Which marketing channels leads to users churning after a month?" or
192
- "What do users do on our website before signing up?". Particularly useful for associating user behaviour before and after
193
- they e.g. register, login, or perform some other identifying action.
327
+ Associate user behaviour before and after they e.g. register, login, or perform some other identifying action.
194
328
 
195
- An `alias` call requires
196
- - `previous distinct id` the unique ID of the user before
197
- - `distinct id` the current unique id
198
-
199
- For example:
200
- ```python
201
- posthog.alias('anonymous session id', 'distinct id')
202
- ```
329
+ Args:
330
+ previous_id: The unique ID of the user before
331
+ distinct_id: The current unique id
332
+ timestamp: Optional timestamp for the event
333
+ uuid: Optional UUID for the event
334
+ disable_geoip: Whether to disable GeoIP lookup
335
+
336
+ Details:
337
+ To marry up whatever a user does before they sign up or log in with what they do after you need to make an alias call. This will allow you to answer questions like "Which marketing channels leads to users churning after a month?" or "What do users do on our website before signing up?". Particularly useful for associating user behaviour before and after they e.g. register, login, or perform some other identifying action.
338
+
339
+ Examples:
340
+ ```python
341
+ # Alias user
342
+ from posthoganalytics import alias
343
+ alias(previous_id='distinct_id', distinct_id='alias_id')
344
+ ```
345
+ Category:
346
+ Identification
203
347
  """
204
348
 
205
349
  return _proxy(
@@ -217,26 +361,25 @@ def capture_exception(
217
361
  **kwargs: Unpack[OptionalCaptureArgs],
218
362
  ):
219
363
  """
220
- capture_exception allows you to capture exceptions that happen in your code.
221
-
222
- Capture exception is idempotent - if it is called twice with the same exception instance, only a occurrence will be tracked in posthog.
223
- This is because, generally, contexts will cause exceptions to be captured automatically. However, to ensure you track an exception,
224
- if you catch and do not re-raise it, capturing it manually is recommended, unless you are certain it will have crossed a context
225
- boundary (e.g. by existing a `with posthog.new_context():` block already)
226
-
227
- A `capture_exception` call does not require any fields, but we recommend passing an exception of some kind:
228
- - `exception` to specify the exception to capture. If not provided, the current exception is captured via `sys.exc_info()`
229
-
230
- If the passed exception was raised and caught, the captured stack trace will consist of every frame between where the exception was raised
231
- and the point at which it is captured (the "traceback").
232
-
233
- If the passed exception was never raised, e.g. if you call `posthog.capture_exception(ValueError("Some Error"))`, the stack trace
234
- captured will be the full stack trace at the moment the exception was captured.
235
-
236
- Note that heavy use of contexts will lead to truncated stack traces, as the exception will be captured by the context entered most recently,
237
- which may not be the point you catch the exception for the final time in your code. It's recommended to use contexts sparingly, for this reason.
364
+ Capture exceptions that happen in your code.
238
365
 
239
- `capture_exception` takes the same set of optional arguments as `capture`.
366
+ Args:
367
+ exception: The exception to capture. If not provided, the current exception is captured via `sys.exc_info()`
368
+
369
+ Details:
370
+ Capture exception is idempotent - if it is called twice with the same exception instance, only a occurrence will be tracked in posthog. This is because, generally, contexts will cause exceptions to be captured automatically. However, to ensure you track an exception, if you catch and do not re-raise it, capturing it manually is recommended, unless you are certain it will have crossed a context boundary (e.g. by existing a `with posthog.new_context():` block already). If the passed exception was raised and caught, the captured stack trace will consist of every frame between where the exception was raised and the point at which it is captured (the "traceback"). If the passed exception was never raised, e.g. if you call `posthog.capture_exception(ValueError("Some Error"))`, the stack trace captured will be the full stack trace at the moment the exception was captured. Note that heavy use of contexts will lead to truncated stack traces, as the exception will be captured by the context entered most recently, which may not be the point you catch the exception for the final time in your code. It's recommended to use contexts sparingly, for this reason. `capture_exception` takes the same set of optional arguments as `capture`.
371
+
372
+ Examples:
373
+ ```python
374
+ # Capture exception
375
+ from posthoganalytics import capture_exception
376
+ try:
377
+ risky_operation()
378
+ except Exception as e:
379
+ capture_exception(e)
380
+ ```
381
+ Category:
382
+ Events
240
383
  """
241
384
 
242
385
  return _proxy("capture_exception", exception=exception, **kwargs)
@@ -256,15 +399,29 @@ def feature_enabled(
256
399
  """
257
400
  Use feature flags to enable or disable features for users.
258
401
 
259
- For example:
260
- ```python
261
- if posthog.feature_enabled('beta feature', 'distinct id'):
262
- # do something
263
- if posthog.feature_enabled('groups feature', 'distinct id', groups={"organization": "5"}):
264
- # do something
265
- ```
266
-
267
- You can call `posthog.load_feature_flags()` before to make sure you're not doing unexpected requests.
402
+ Args:
403
+ key: The feature flag key
404
+ distinct_id: The user's distinct ID
405
+ groups: Groups mapping
406
+ person_properties: Person properties
407
+ group_properties: Group properties
408
+ only_evaluate_locally: Whether to evaluate only locally
409
+ send_feature_flag_events: Whether to send feature flag events
410
+ disable_geoip: Whether to disable GeoIP lookup
411
+
412
+ Details:
413
+ You can call `posthog.load_feature_flags()` before to make sure you're not doing unexpected requests.
414
+
415
+ Examples:
416
+ ```python
417
+ # Boolean feature flag
418
+ from posthoganalytics import feature_enabled, get_feature_flag_payload
419
+ is_my_flag_enabled = feature_enabled('flag-key', 'distinct_id_of_your_user')
420
+ if is_my_flag_enabled:
421
+ matched_flag_payload = get_feature_flag_payload('flag-key', 'distinct_id_of_your_user')
422
+ ```
423
+ Category:
424
+ Feature flags
268
425
  """
269
426
  return _proxy(
270
427
  "feature_enabled",
@@ -291,25 +448,30 @@ def get_feature_flag(
291
448
  ) -> Optional[FeatureFlag]:
292
449
  """
293
450
  Get feature flag variant for users. Used with experiments.
294
- Example:
295
- ```python
296
- if posthog.get_feature_flag('beta-feature', 'distinct_id') == 'test-variant':
297
- # do test variant code
298
- if posthog.get_feature_flag('beta-feature', 'distinct_id') == 'control':
299
- # do control code
300
- ```
301
-
302
- `groups` are a mapping from group type to group key. So, if you have a group type of "organization" and a group key of "5",
303
- you would pass groups={"organization": "5"}.
304
-
305
- `group_properties` take the format: { group_type_name: { group_properties } }
306
451
 
307
- So, for example, if you have the group type "organization" and the group key "5", with the properties name, and employee count,
308
- you'll send these as:
309
-
310
- ```python
311
- group_properties={"organization": {"name": "PostHog", "employees": 11}}
312
- ```
452
+ Args:
453
+ key: The feature flag key
454
+ distinct_id: The user's distinct ID
455
+ groups: Groups mapping from group type to group key
456
+ person_properties: Person properties
457
+ group_properties: Group properties in format { group_type_name: { group_properties } }
458
+ only_evaluate_locally: Whether to evaluate only locally
459
+ send_feature_flag_events: Whether to send feature flag events
460
+ disable_geoip: Whether to disable GeoIP lookup
461
+
462
+ Details:
463
+ `groups` are a mapping from group type to group key. So, if you have a group type of "organization" and a group key of "5", you would pass groups={"organization": "5"}. `group_properties` take the format: { group_type_name: { group_properties } }. So, for example, if you have the group type "organization" and the group key "5", with the properties name, and employee count, you'll send these as: group_properties={"organization": {"name": "PostHog", "employees": 11}}.
464
+
465
+ Examples:
466
+ ```python
467
+ # Multivariate feature flag
468
+ from posthoganalytics import get_feature_flag, get_feature_flag_payload
469
+ enabled_variant = get_feature_flag('flag-key', 'distinct_id_of_your_user')
470
+ if enabled_variant == 'variant-key':
471
+ matched_flag_payload = get_feature_flag_payload('flag-key', 'distinct_id_of_your_user')
472
+ ```
473
+ Category:
474
+ Feature flags
313
475
  """
314
476
  return _proxy(
315
477
  "get_feature_flag",
@@ -334,12 +496,26 @@ def get_all_flags(
334
496
  ) -> Optional[dict[str, FeatureFlag]]:
335
497
  """
336
498
  Get all flags for a given user.
337
- Example:
338
- ```python
339
- flags = posthog.get_all_flags('distinct_id')
340
- ```
341
499
 
342
- flags are key-value pairs where the key is the flag key and the value is the flag variant, or True, or False.
500
+ Args:
501
+ distinct_id: The user's distinct ID
502
+ groups: Groups mapping
503
+ person_properties: Person properties
504
+ group_properties: Group properties
505
+ only_evaluate_locally: Whether to evaluate only locally
506
+ disable_geoip: Whether to disable GeoIP lookup
507
+
508
+ Details:
509
+ Flags are key-value pairs where the key is the flag key and the value is the flag variant, or True, or False.
510
+
511
+ Examples:
512
+ ```python
513
+ # All flags for user
514
+ from posthoganalytics import get_all_flags
515
+ get_all_flags('distinct_id_of_your_user')
516
+ ```
517
+ Category:
518
+ Feature flags
343
519
  """
344
520
  return _proxy(
345
521
  "get_all_flags",
@@ -417,27 +593,85 @@ def get_all_flags_and_payloads(
417
593
 
418
594
 
419
595
  def feature_flag_definitions():
420
- """Returns loaded feature flags, if any. Helpful for debugging what flag information you have loaded."""
596
+ """
597
+ Returns loaded feature flags.
598
+
599
+ Details:
600
+ Returns loaded feature flags, if any. Helpful for debugging what flag information you have loaded.
601
+
602
+ Examples:
603
+ ```python
604
+ from posthoganalytics import feature_flag_definitions
605
+ definitions = feature_flag_definitions()
606
+ ```
607
+
608
+ Category:
609
+ Feature flags
610
+ """
421
611
  return _proxy("feature_flag_definitions")
422
612
 
423
613
 
424
614
  def load_feature_flags():
425
- """Load feature flag definitions from PostHog."""
615
+ """
616
+ Load feature flag definitions from PostHog.
617
+
618
+ Examples:
619
+ ```python
620
+ from posthoganalytics import load_feature_flags
621
+ load_feature_flags()
622
+ ```
623
+
624
+ Category:
625
+ Feature flags
626
+ """
426
627
  return _proxy("load_feature_flags")
427
628
 
428
629
 
429
630
  def flush():
430
- """Tell the client to flush."""
631
+ """
632
+ Tell the client to flush all queued events.
633
+
634
+ Examples:
635
+ ```python
636
+ from posthoganalytics import flush
637
+ flush()
638
+ ```
639
+
640
+ Category:
641
+ Client management
642
+ """
431
643
  _proxy("flush")
432
644
 
433
645
 
434
646
  def join():
435
- """Block program until the client clears the queue"""
647
+ """
648
+ Block program until the client clears the queue. Used during program shutdown. You should use `shutdown()` directly in most cases.
649
+
650
+ Examples:
651
+ ```python
652
+ from posthoganalytics import join
653
+ join()
654
+ ```
655
+
656
+ Category:
657
+ Client management
658
+ """
436
659
  _proxy("join")
437
660
 
438
661
 
439
662
  def shutdown():
440
- """Flush all messages and cleanly shutdown the client"""
663
+ """
664
+ Flush all messages and cleanly shutdown the client.
665
+
666
+ Examples:
667
+ ```python
668
+ from posthoganalytics import shutdown
669
+ shutdown()
670
+ ```
671
+
672
+ Category:
673
+ Client management
674
+ """
441
675
  _proxy("flush")
442
676
  _proxy("join")
443
677
 
@@ -465,6 +699,7 @@ def setup():
465
699
  # or deprecate this proxy option fully (it's already in the process of deprecation, no new clients should be using this method since like 5-6 months)
466
700
  enable_exception_autocapture=enable_exception_autocapture,
467
701
  log_captured_exceptions=log_captured_exceptions,
702
+ enable_local_evaluation=enable_local_evaluation,
468
703
  )
469
704
 
470
705
  # always set incase user changes it