Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5e8b7d7fb | ||
|
|
efb0ccf3c7 | ||
|
|
8554b51a48 |
@@ -1,3 +1,15 @@
|
||||
## 3.4.0 - 2024-02-05
|
||||
|
||||
1. Point given hosts to new ingestion hosts
|
||||
|
||||
## 3.3.4 - 2024-01-30
|
||||
|
||||
1. Update type hints for module variables to work with newer versions of mypy
|
||||
|
||||
## 3.3.3 - 2024-01-26
|
||||
|
||||
1. Remove new relative date operators, combine into regular date operators
|
||||
|
||||
## 3.3.2 - 2024-01-19
|
||||
|
||||
1. Return success/failure with all capture calls from module functions
|
||||
|
||||
+11
-6
@@ -7,19 +7,19 @@ from posthog.version import VERSION
|
||||
__version__ = VERSION
|
||||
|
||||
"""Settings."""
|
||||
api_key = None # type: str
|
||||
host = None # type: str
|
||||
on_error = None # type: Callable
|
||||
api_key = None # type: Optional[str]
|
||||
host = None # type: Optional[str]
|
||||
on_error = None # type: Optional[Callable]
|
||||
debug = False # type: bool
|
||||
send = True # type: bool
|
||||
sync_mode = False # type: bool
|
||||
disabled = False # type: bool
|
||||
personal_api_key = None # type: str
|
||||
project_api_key = None # type: str
|
||||
personal_api_key = None # type: Optional[str]
|
||||
project_api_key = None # type: Optional[str]
|
||||
poll_interval = 30 # type: int
|
||||
disable_geoip = True # type: bool
|
||||
|
||||
default_client = None
|
||||
default_client = None # type: Optional[Client]
|
||||
|
||||
|
||||
def capture(
|
||||
@@ -405,6 +405,11 @@ def feature_flag_definitions():
|
||||
return _proxy("feature_flag_definitions")
|
||||
|
||||
|
||||
def load_feature_flags():
|
||||
"""Load feature flag definitions from PostHog."""
|
||||
return _proxy("load_feature_flags")
|
||||
|
||||
|
||||
def page(*args, **kwargs):
|
||||
"""Send a page call."""
|
||||
_proxy("page", *args, **kwargs)
|
||||
|
||||
+25
-8
@@ -10,7 +10,7 @@ from six import string_types
|
||||
from posthog.consumer import Consumer
|
||||
from posthog.feature_flags import InconclusiveMatchError, match_feature_flag_properties
|
||||
from posthog.poller import Poller
|
||||
from posthog.request import APIError, batch_post, decide, get
|
||||
from posthog.request import APIError, batch_post, decide, determine_server_host, get
|
||||
from posthog.utils import SizeLimitedDict, clean, guess_timezone
|
||||
from posthog.version import VERSION
|
||||
|
||||
@@ -61,7 +61,7 @@ class Client(object):
|
||||
self.debug = debug
|
||||
self.send = send
|
||||
self.sync_mode = sync_mode
|
||||
self.host = host
|
||||
self.host = determine_server_host(host)
|
||||
self.gzip = gzip
|
||||
self.timeout = timeout
|
||||
self.feature_flags = None
|
||||
@@ -464,7 +464,16 @@ class Client(object):
|
||||
self.poller = Poller(interval=timedelta(seconds=self.poll_interval), execute=self._load_feature_flags)
|
||||
self.poller.start()
|
||||
|
||||
def _compute_flag_locally(self, feature_flag, distinct_id, *, groups={}, person_properties={}, group_properties={}):
|
||||
def _compute_flag_locally(
|
||||
self,
|
||||
feature_flag,
|
||||
distinct_id,
|
||||
*,
|
||||
groups={},
|
||||
person_properties={},
|
||||
group_properties={},
|
||||
warn_on_unknown_groups=True,
|
||||
):
|
||||
if feature_flag.get("ensure_experience_continuity", False):
|
||||
raise InconclusiveMatchError("Flag has experience continuity enabled")
|
||||
|
||||
@@ -486,9 +495,14 @@ class Client(object):
|
||||
if group_name not in groups:
|
||||
# Group flags are never enabled in `groups` aren't passed in
|
||||
# don't failover to `/decide/`, since response will be the same
|
||||
self.log.warning(
|
||||
f"[FEATURE FLAGS] Can't compute group feature flag: {feature_flag['key']} without group names passed in"
|
||||
)
|
||||
if warn_on_unknown_groups:
|
||||
self.log.warning(
|
||||
f"[FEATURE FLAGS] Can't compute group feature flag: {feature_flag['key']} without group names passed in"
|
||||
)
|
||||
else:
|
||||
self.log.debug(
|
||||
f"[FEATURE FLAGS] Can't compute group feature flag: {feature_flag['key']} without group names passed in"
|
||||
)
|
||||
return False
|
||||
|
||||
focused_group_properties = group_properties[group_name]
|
||||
@@ -717,7 +731,9 @@ class Client(object):
|
||||
|
||||
return response
|
||||
|
||||
def _get_all_flags_and_payloads_locally(self, distinct_id, *, groups={}, person_properties={}, group_properties={}):
|
||||
def _get_all_flags_and_payloads_locally(
|
||||
self, distinct_id, *, groups={}, person_properties={}, group_properties={}, warn_on_unknown_groups=False
|
||||
):
|
||||
require("distinct_id", distinct_id, ID_TYPES)
|
||||
require("groups", groups, dict)
|
||||
|
||||
@@ -737,6 +753,7 @@ class Client(object):
|
||||
groups=groups,
|
||||
person_properties=person_properties,
|
||||
group_properties=group_properties,
|
||||
warn_on_unknown_groups=warn_on_unknown_groups,
|
||||
)
|
||||
matched_payload = self._compute_payload_locally(flag["key"], flags[flag["key"]])
|
||||
if matched_payload:
|
||||
@@ -756,7 +773,7 @@ class Client(object):
|
||||
return self.feature_flags
|
||||
|
||||
def _add_local_person_and_group_properties(self, distinct_id, groups, person_properties, group_properties):
|
||||
all_person_properties = {"$current_distinct_id": distinct_id, **(person_properties or {})}
|
||||
all_person_properties = {"distinct_id": distinct_id, **(person_properties or {})}
|
||||
|
||||
all_group_properties = {}
|
||||
if groups:
|
||||
|
||||
@@ -175,11 +175,11 @@ def match_property(property, property_values) -> bool:
|
||||
else:
|
||||
return compare(str(override_value), str(value), operator)
|
||||
|
||||
if operator in ["is_date_before", "is_date_after", "is_relative_date_before", "is_relative_date_after"]:
|
||||
if operator in ["is_date_before", "is_date_after"]:
|
||||
try:
|
||||
if operator in ["is_relative_date_before", "is_relative_date_after"]:
|
||||
parsed_date = relative_date_parse_for_feature_flag_matching(str(value))
|
||||
else:
|
||||
parsed_date = relative_date_parse_for_feature_flag_matching(str(value))
|
||||
|
||||
if not parsed_date:
|
||||
parsed_date = parser.parse(str(value))
|
||||
parsed_date = convert_to_datetime_aware(parsed_date)
|
||||
except Exception as e:
|
||||
@@ -190,12 +190,12 @@ def match_property(property, property_values) -> bool:
|
||||
|
||||
if isinstance(override_value, datetime.datetime):
|
||||
override_date = convert_to_datetime_aware(override_value)
|
||||
if operator in ("is_date_before", "is_relative_date_before"):
|
||||
if operator == "is_date_before":
|
||||
return override_date < parsed_date
|
||||
else:
|
||||
return override_date > parsed_date
|
||||
elif isinstance(override_value, datetime.date):
|
||||
if operator in ("is_date_before", "is_relative_date_before"):
|
||||
if operator == "is_date_before":
|
||||
return override_value < parsed_date.date()
|
||||
else:
|
||||
return override_value > parsed_date.date()
|
||||
@@ -203,7 +203,7 @@ def match_property(property, property_values) -> bool:
|
||||
try:
|
||||
override_date = parser.parse(override_value)
|
||||
override_date = convert_to_datetime_aware(override_date)
|
||||
if operator in ("is_date_before", "is_relative_date_before"):
|
||||
if operator == "is_date_before":
|
||||
return override_date < parsed_date
|
||||
else:
|
||||
return override_date > parsed_date
|
||||
@@ -302,7 +302,7 @@ def match_property_group(property_group, property_values, cohort_properties) ->
|
||||
|
||||
|
||||
def relative_date_parse_for_feature_flag_matching(value: str) -> Optional[datetime.datetime]:
|
||||
regex = r"^(?P<number>[0-9]+)(?P<interval>[a-z])$"
|
||||
regex = r"^-?(?P<number>[0-9]+)(?P<interval>[a-z])$"
|
||||
match = re.search(regex, value)
|
||||
parsed_dt = datetime.datetime.now(datetime.timezone.utc)
|
||||
if match:
|
||||
|
||||
+15
-1
@@ -13,10 +13,24 @@ from posthog.version import VERSION
|
||||
|
||||
_session = requests.sessions.Session()
|
||||
|
||||
DEFAULT_HOST = "https://app.posthog.com"
|
||||
US_INGESTION_ENDPOINT = "https://us-api.i.posthog.com"
|
||||
EU_INGESTION_ENDPOINT = "https://eu-api.i.posthog.com"
|
||||
DEFAULT_HOST = US_INGESTION_ENDPOINT
|
||||
USER_AGENT = "posthog-python/" + VERSION
|
||||
|
||||
|
||||
def determine_server_host(host: Optional[str]) -> str:
|
||||
"""Determines the server host to use."""
|
||||
host_or_default = host or DEFAULT_HOST
|
||||
trimmed_host = remove_trailing_slash(host_or_default)
|
||||
if trimmed_host in ("https://app.posthog.com", "https://us.posthog.com"):
|
||||
return US_INGESTION_ENDPOINT
|
||||
elif trimmed_host == "https://eu.posthog.com":
|
||||
return EU_INGESTION_ENDPOINT
|
||||
else:
|
||||
return host_or_default
|
||||
|
||||
|
||||
def post(
|
||||
api_key: str, host: Optional[str] = None, path=None, gzip: bool = False, timeout: int = 15, **kwargs
|
||||
) -> requests.Response:
|
||||
|
||||
@@ -43,9 +43,9 @@ class PostHogIntegration(Integration):
|
||||
not not Hub.current.client.dsn and Dsn(Hub.current.client.dsn).project_id
|
||||
)
|
||||
if project_id:
|
||||
properties[
|
||||
"$sentry_url"
|
||||
] = f"{PostHogIntegration.prefix}{PostHogIntegration.organization}/issues/?project={project_id}&query={event['event_id']}"
|
||||
properties["$sentry_url"] = (
|
||||
f"{PostHogIntegration.prefix}{PostHogIntegration.organization}/issues/?project={project_id}&query={event['event_id']}"
|
||||
)
|
||||
|
||||
posthog.capture(posthog_distinct_id, "$exception", properties)
|
||||
|
||||
|
||||
+21
-17
@@ -314,7 +314,7 @@ class TestClient(unittest.TestCase):
|
||||
self.assertEqual(patch_decide.call_count, 1)
|
||||
patch_decide.assert_called_with(
|
||||
"random_key",
|
||||
None,
|
||||
"https://us-api.i.posthog.com",
|
||||
timeout=10,
|
||||
distinct_id="distinct_id",
|
||||
groups={},
|
||||
@@ -330,7 +330,11 @@ class TestClient(unittest.TestCase):
|
||||
}
|
||||
|
||||
client = Client(
|
||||
FAKE_TEST_API_KEY, on_error=self.set_fail, personal_api_key=FAKE_TEST_API_KEY, disable_geoip=True
|
||||
FAKE_TEST_API_KEY,
|
||||
host="https://app.posthog.com",
|
||||
on_error=self.set_fail,
|
||||
personal_api_key=FAKE_TEST_API_KEY,
|
||||
disable_geoip=True,
|
||||
)
|
||||
success, msg = client.capture("distinct_id", "python test event", send_feature_flags=True, disable_geoip=False)
|
||||
client.flush()
|
||||
@@ -351,7 +355,7 @@ class TestClient(unittest.TestCase):
|
||||
self.assertEqual(patch_decide.call_count, 1)
|
||||
patch_decide.assert_called_with(
|
||||
"random_key",
|
||||
None,
|
||||
"https://us-api.i.posthog.com",
|
||||
timeout=10,
|
||||
distinct_id="distinct_id",
|
||||
groups={},
|
||||
@@ -779,11 +783,11 @@ class TestClient(unittest.TestCase):
|
||||
client.get_feature_flag("random_key", "some_id", disable_geoip=True)
|
||||
patch_decide.assert_called_with(
|
||||
"random_key",
|
||||
None,
|
||||
"https://us-api.i.posthog.com",
|
||||
timeout=10,
|
||||
distinct_id="some_id",
|
||||
groups={},
|
||||
person_properties={"$current_distinct_id": "some_id"},
|
||||
person_properties={"distinct_id": "some_id"},
|
||||
group_properties={},
|
||||
disable_geoip=True,
|
||||
)
|
||||
@@ -791,11 +795,11 @@ class TestClient(unittest.TestCase):
|
||||
client.feature_enabled("random_key", "feature_enabled_distinct_id", disable_geoip=True)
|
||||
patch_decide.assert_called_with(
|
||||
"random_key",
|
||||
None,
|
||||
"https://us-api.i.posthog.com",
|
||||
timeout=10,
|
||||
distinct_id="feature_enabled_distinct_id",
|
||||
groups={},
|
||||
person_properties={"$current_distinct_id": "feature_enabled_distinct_id"},
|
||||
person_properties={"distinct_id": "feature_enabled_distinct_id"},
|
||||
group_properties={},
|
||||
disable_geoip=True,
|
||||
)
|
||||
@@ -803,11 +807,11 @@ class TestClient(unittest.TestCase):
|
||||
client.get_all_flags_and_payloads("all_flags_payloads_id")
|
||||
patch_decide.assert_called_with(
|
||||
"random_key",
|
||||
None,
|
||||
"https://us-api.i.posthog.com",
|
||||
timeout=10,
|
||||
distinct_id="all_flags_payloads_id",
|
||||
groups={},
|
||||
person_properties={"$current_distinct_id": "all_flags_payloads_id"},
|
||||
person_properties={"distinct_id": "all_flags_payloads_id"},
|
||||
group_properties={},
|
||||
disable_geoip=False,
|
||||
)
|
||||
@@ -829,7 +833,7 @@ class TestClient(unittest.TestCase):
|
||||
patch_decide.return_value = {
|
||||
"featureFlags": {"beta-feature": "random-variant", "alpha-feature": True, "off-feature": False}
|
||||
}
|
||||
client = Client(FAKE_TEST_API_KEY, on_error=self.set_fail, disable_geoip=False)
|
||||
client = Client(FAKE_TEST_API_KEY, host="http://app2.posthog.com", on_error=self.set_fail, disable_geoip=False)
|
||||
client.get_feature_flag(
|
||||
"random_key",
|
||||
"some_id",
|
||||
@@ -839,11 +843,11 @@ class TestClient(unittest.TestCase):
|
||||
)
|
||||
patch_decide.assert_called_with(
|
||||
"random_key",
|
||||
None,
|
||||
"http://app2.posthog.com",
|
||||
timeout=10,
|
||||
distinct_id="some_id",
|
||||
groups={"company": "id:5", "instance": "app.posthog.com"},
|
||||
person_properties={"$current_distinct_id": "some_id", "x1": "y1"},
|
||||
person_properties={"distinct_id": "some_id", "x1": "y1"},
|
||||
group_properties={
|
||||
"company": {"$group_key": "id:5", "x": "y"},
|
||||
"instance": {"$group_key": "app.posthog.com"},
|
||||
@@ -856,7 +860,7 @@ class TestClient(unittest.TestCase):
|
||||
"random_key",
|
||||
"some_id",
|
||||
groups={"company": "id:5", "instance": "app.posthog.com"},
|
||||
person_properties={"$current_distinct_id": "override"},
|
||||
person_properties={"distinct_id": "override"},
|
||||
group_properties={
|
||||
"company": {
|
||||
"$group_key": "group_override",
|
||||
@@ -865,11 +869,11 @@ class TestClient(unittest.TestCase):
|
||||
)
|
||||
patch_decide.assert_called_with(
|
||||
"random_key",
|
||||
None,
|
||||
"http://app2.posthog.com",
|
||||
timeout=10,
|
||||
distinct_id="some_id",
|
||||
groups={"company": "id:5", "instance": "app.posthog.com"},
|
||||
person_properties={"$current_distinct_id": "override"},
|
||||
person_properties={"distinct_id": "override"},
|
||||
group_properties={
|
||||
"company": {"$group_key": "group_override"},
|
||||
"instance": {"$group_key": "app.posthog.com"},
|
||||
@@ -882,11 +886,11 @@ class TestClient(unittest.TestCase):
|
||||
client.get_all_flags_and_payloads("some_id", groups={}, person_properties=None, group_properties=None)
|
||||
patch_decide.assert_called_with(
|
||||
"random_key",
|
||||
None,
|
||||
"http://app2.posthog.com",
|
||||
timeout=10,
|
||||
distinct_id="some_id",
|
||||
groups={},
|
||||
person_properties={"$current_distinct_id": "some_id"},
|
||||
person_properties={"distinct_id": "some_id"},
|
||||
group_properties={},
|
||||
disable_geoip=False,
|
||||
)
|
||||
|
||||
@@ -1873,7 +1873,7 @@ class TestMatchProperties(unittest.TestCase):
|
||||
|
||||
@freeze_time("2022-05-01")
|
||||
def test_match_property_relative_date_operators(self):
|
||||
property_a = self.property(key="key", value="6h", operator="is_relative_date_before")
|
||||
property_a = self.property(key="key", value="-6h", operator="is_date_before")
|
||||
self.assertTrue(match_property(property_a, {"key": "2022-03-01"}))
|
||||
self.assertTrue(match_property(property_a, {"key": "2022-04-30"}))
|
||||
self.assertTrue(match_property(property_a, {"key": datetime.datetime(2022, 4, 30, 1, 2, 3)}))
|
||||
@@ -1898,7 +1898,7 @@ class TestMatchProperties(unittest.TestCase):
|
||||
with self.assertRaises(InconclusiveMatchError):
|
||||
match_property(property_a, {"key": "abcdef"})
|
||||
|
||||
property_b = self.property(key="key", value="1h", operator="is_relative_date_after")
|
||||
property_b = self.property(key="key", value="1h", operator="is_date_after")
|
||||
self.assertTrue(match_property(property_b, {"key": "2022-05-02"}))
|
||||
self.assertTrue(match_property(property_b, {"key": "2022-05-30"}))
|
||||
self.assertTrue(match_property(property_b, {"key": datetime.datetime(2022, 5, 30)}))
|
||||
@@ -1910,16 +1910,16 @@ class TestMatchProperties(unittest.TestCase):
|
||||
self.assertFalse(match_property(property_b, {"key": "abcdef"}))
|
||||
|
||||
# Invalid flag property
|
||||
property_c = self.property(key="key", value=1234, operator="is_relative_date_after")
|
||||
property_c = self.property(key="key", value=1234, operator="is_date_after")
|
||||
|
||||
with self.assertRaises(InconclusiveMatchError):
|
||||
self.assertFalse(match_property(property_c, {"key": 1}))
|
||||
|
||||
with self.assertRaises(InconclusiveMatchError):
|
||||
self.assertFalse(match_property(property_c, {"key": "2022-05-30"}))
|
||||
# parsed as 1234-05-01 for some reason?
|
||||
self.assertTrue(match_property(property_c, {"key": "2022-05-30"}))
|
||||
|
||||
# # Timezone aware property
|
||||
property_d = self.property(key="key", value="12d", operator="is_relative_date_before")
|
||||
property_d = self.property(key="key", value="12d", operator="is_date_before")
|
||||
self.assertFalse(match_property(property_d, {"key": "2022-05-30"}))
|
||||
|
||||
self.assertTrue(match_property(property_d, {"key": "2022-03-30"}))
|
||||
@@ -1929,45 +1929,45 @@ class TestMatchProperties(unittest.TestCase):
|
||||
self.assertFalse(match_property(property_d, {"key": "2022-04-19 02:00:01+02:00"}))
|
||||
|
||||
# Try all possible relative dates
|
||||
property_e = self.property(key="key", value="1h", operator="is_relative_date_before")
|
||||
property_e = self.property(key="key", value="1h", operator="is_date_before")
|
||||
self.assertFalse(match_property(property_e, {"key": "2022-05-01 00:00:00"}))
|
||||
self.assertTrue(match_property(property_e, {"key": "2022-04-30 22:00:00"}))
|
||||
|
||||
property_f = self.property(key="key", value="1d", operator="is_relative_date_before")
|
||||
property_f = self.property(key="key", value="-1d", operator="is_date_before")
|
||||
self.assertTrue(match_property(property_f, {"key": "2022-04-29 23:59:00"}))
|
||||
self.assertFalse(match_property(property_f, {"key": "2022-04-30 00:00:01"}))
|
||||
|
||||
property_g = self.property(key="key", value="1w", operator="is_relative_date_before")
|
||||
property_g = self.property(key="key", value="1w", operator="is_date_before")
|
||||
self.assertTrue(match_property(property_g, {"key": "2022-04-23 00:00:00"}))
|
||||
self.assertFalse(match_property(property_g, {"key": "2022-04-24 00:00:00"}))
|
||||
self.assertFalse(match_property(property_g, {"key": "2022-04-24 00:00:01"}))
|
||||
|
||||
property_h = self.property(key="key", value="1m", operator="is_relative_date_before")
|
||||
property_h = self.property(key="key", value="1m", operator="is_date_before")
|
||||
self.assertTrue(match_property(property_h, {"key": "2022-03-01 00:00:00"}))
|
||||
self.assertFalse(match_property(property_h, {"key": "2022-04-05 00:00:00"}))
|
||||
|
||||
property_i = self.property(key="key", value="1y", operator="is_relative_date_before")
|
||||
property_i = self.property(key="key", value="1y", operator="is_date_before")
|
||||
self.assertTrue(match_property(property_i, {"key": "2021-04-28 00:00:00"}))
|
||||
self.assertFalse(match_property(property_i, {"key": "2021-05-01 00:00:01"}))
|
||||
|
||||
property_j = self.property(key="key", value="122h", operator="is_relative_date_after")
|
||||
property_j = self.property(key="key", value="122h", operator="is_date_after")
|
||||
self.assertTrue(match_property(property_j, {"key": "2022-05-01 00:00:00"}))
|
||||
self.assertFalse(match_property(property_j, {"key": "2022-04-23 01:00:00"}))
|
||||
|
||||
property_k = self.property(key="key", value="2d", operator="is_relative_date_after")
|
||||
property_k = self.property(key="key", value="2d", operator="is_date_after")
|
||||
self.assertTrue(match_property(property_k, {"key": "2022-05-01 00:00:00"}))
|
||||
self.assertTrue(match_property(property_k, {"key": "2022-04-29 00:00:01"}))
|
||||
self.assertFalse(match_property(property_k, {"key": "2022-04-29 00:00:00"}))
|
||||
|
||||
property_l = self.property(key="key", value="02w", operator="is_relative_date_after")
|
||||
property_l = self.property(key="key", value="-02w", operator="is_date_after")
|
||||
self.assertTrue(match_property(property_l, {"key": "2022-05-01 00:00:00"}))
|
||||
self.assertFalse(match_property(property_l, {"key": "2022-04-16 00:00:00"}))
|
||||
|
||||
property_m = self.property(key="key", value="1m", operator="is_relative_date_after")
|
||||
property_m = self.property(key="key", value="1m", operator="is_date_after")
|
||||
self.assertTrue(match_property(property_m, {"key": "2022-04-01 00:00:01"}))
|
||||
self.assertFalse(match_property(property_m, {"key": "2022-04-01 00:00:00"}))
|
||||
|
||||
property_n = self.property(key="key", value="1y", operator="is_relative_date_after")
|
||||
property_n = self.property(key="key", value="1y", operator="is_date_after")
|
||||
self.assertTrue(match_property(property_n, {"key": "2022-05-01 00:00:00"}))
|
||||
self.assertTrue(match_property(property_n, {"key": "2021-05-01 00:00:01"}))
|
||||
self.assertFalse(match_property(property_n, {"key": "2021-05-01 00:00:00"}))
|
||||
|
||||
@@ -2,9 +2,10 @@ import json
|
||||
import unittest
|
||||
from datetime import date, datetime
|
||||
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
from posthog.request import DatetimeSerializer, batch_post
|
||||
from posthog.request import DatetimeSerializer, batch_post, determine_server_host
|
||||
from posthog.test.test_utils import TEST_API_KEY
|
||||
|
||||
|
||||
@@ -42,3 +43,26 @@ class TestRequests(unittest.TestCase):
|
||||
batch_post(
|
||||
"key", batch=[{"distinct_id": "distinct_id", "event": "python event", "type": "track"}], timeout=0.0001
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"host, expected",
|
||||
[
|
||||
("https://t.posthog.com", "https://t.posthog.com"),
|
||||
("https://t.posthog.com/", "https://t.posthog.com/"),
|
||||
("t.posthog.com", "t.posthog.com"),
|
||||
("t.posthog.com/", "t.posthog.com/"),
|
||||
("https://us.posthog.com.rg.proxy.com", "https://us.posthog.com.rg.proxy.com"),
|
||||
("app.posthog.com", "app.posthog.com"),
|
||||
("eu.posthog.com", "eu.posthog.com"),
|
||||
("https://app.posthog.com", "https://us-api.i.posthog.com"),
|
||||
("https://eu.posthog.com", "https://eu-api.i.posthog.com"),
|
||||
("https://us.posthog.com", "https://us-api.i.posthog.com"),
|
||||
("https://app.posthog.com/", "https://us-api.i.posthog.com"),
|
||||
("https://eu.posthog.com/", "https://eu-api.i.posthog.com"),
|
||||
("https://us.posthog.com/", "https://us-api.i.posthog.com"),
|
||||
(None, "https://us-api.i.posthog.com"),
|
||||
],
|
||||
)
|
||||
def test_routing_to_custom_host(host, expected):
|
||||
assert determine_server_host(host) == expected
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
VERSION = "3.3.2"
|
||||
VERSION = "3.4.0"
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(VERSION, end="") # noqa: T201
|
||||
|
||||
@@ -13,6 +13,7 @@ Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
|
||||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
|
||||
|
||||
Reference in New Issue
Block a user