diff --git a/ee/billing/quota_limiting.py b/ee/billing/quota_limiting.py index 7e2efc4357ca5..1c50b69803a57 100644 --- a/ee/billing/quota_limiting.py +++ b/ee/billing/quota_limiting.py @@ -327,17 +327,17 @@ def update_all_org_billing_quotas( period_start, period_end = period # Clickhouse is good at counting things so we count across all teams rather than doing it one by one - all_data = dict( - teams_with_event_count_in_period=convert_team_usage_rows_to_dict( + all_data = { + "teams_with_event_count_in_period": convert_team_usage_rows_to_dict( get_teams_with_billable_event_count_in_period(period_start, period_end) ), - teams_with_recording_count_in_period=convert_team_usage_rows_to_dict( + "teams_with_recording_count_in_period": convert_team_usage_rows_to_dict( get_teams_with_recording_count_in_period(period_start, period_end) ), - teams_with_rows_synced_in_period=convert_team_usage_rows_to_dict( + "teams_with_rows_synced_in_period": convert_team_usage_rows_to_dict( get_teams_with_rows_synced_in_period(period_start, period_end) ), - ) + } teams: Sequence[Team] = list( Team.objects.select_related("organization") diff --git a/ee/billing/test/test_quota_limiting.py b/ee/billing/test/test_quota_limiting.py index 7a00a622cde5a..eeba7d97bcf95 100644 --- a/ee/billing/test/test_quota_limiting.py +++ b/ee/billing/test/test_quota_limiting.py @@ -440,15 +440,15 @@ def test_set_org_usage_summary_updates_correctly(self): } self.organization.save() - new_usage = dict( - events={"usage": 100, "limit": 100}, - recordings={"usage": 2, "limit": 100}, - rows_synced={"usage": 6, "limit": 100}, - period=[ + new_usage = { + "events": {"usage": 100, "limit": 100}, + "recordings": {"usage": 2, "limit": 100}, + "rows_synced": {"usage": 6, "limit": 100}, + "period": [ "2021-01-01T00:00:00Z", "2021-01-31T23:59:59Z", ], - ) + } assert set_org_usage_summary(self.organization, new_usage=new_usage) @@ -468,15 +468,15 @@ def test_set_org_usage_summary_does_nothing_if_the_same(self): } self.organization.save() - new_usage = dict( - events={"usage": 99, "limit": 100}, - recordings={"usage": 1, "limit": 100}, - rows_synced={"usage": 5, "limit": 100}, - period=[ + new_usage = { + "events": {"usage": 99, "limit": 100}, + "recordings": {"usage": 1, "limit": 100}, + "rows_synced": {"usage": 5, "limit": 100}, + "period": [ "2021-01-01T00:00:00Z", "2021-01-31T23:59:59Z", ], - ) + } assert not set_org_usage_summary(self.organization, new_usage=new_usage) diff --git a/ee/clickhouse/materialized_columns/analyze.py b/ee/clickhouse/materialized_columns/analyze.py index 6fc3c75036506..dac1aa6abc0f4 100644 --- a/ee/clickhouse/materialized_columns/analyze.py +++ b/ee/clickhouse/materialized_columns/analyze.py @@ -58,7 +58,7 @@ def group_on_events_properties(self, group_type_index: int, team_id: str) -> Set def _get_properties(self, query, team_id) -> Set[str]: rows = sync_execute(query, {"team_id": team_id}) - return set(name for name, _ in rows) + return {name for name, _ in rows} class Query: diff --git a/ee/clickhouse/models/test/test_property.py b/ee/clickhouse/models/test/test_property.py index d12d4daf3eeac..95f863bfe1902 100644 --- a/ee/clickhouse/models/test/test_property.py +++ b/ee/clickhouse/models/test/test_property.py @@ -1773,18 +1773,16 @@ def clean_up_materialised_columns(): @freeze_time("2021-04-01T01:00:00.000Z") def test_prop_filter_json_extract(test_events, clean_up_materialised_columns, property, expected_event_indexes, team): query, params = prop_filter_json_extract(property, 0, allow_denormalized_props=False) - uuids = list( - sorted( - [ - str(uuid) - for (uuid,) in sync_execute( - f"SELECT uuid FROM events WHERE team_id = %(team_id)s {query}", - {"team_id": team.pk, **params}, - ) - ] - ) + uuids = sorted( + [ + str(uuid) + for (uuid,) in sync_execute( + f"SELECT uuid FROM events WHERE team_id = %(team_id)s {query}", + {"team_id": team.pk, **params}, + ) + ] ) - expected = list(sorted([test_events[index] for index in expected_event_indexes])) + expected = sorted([test_events[index] for index in expected_event_indexes]) assert len(uuids) == len(expected) # helpful when diagnosing assertion failure below assert uuids == expected @@ -1801,18 +1799,16 @@ def test_prop_filter_json_extract_materialized( assert "JSONExtract" not in query - uuids = list( - sorted( - [ - str(uuid) - for (uuid,) in sync_execute( - f"SELECT uuid FROM events WHERE team_id = %(team_id)s {query}", - {"team_id": team.pk, **params}, - ) - ] - ) + uuids = sorted( + [ + str(uuid) + for (uuid,) in sync_execute( + f"SELECT uuid FROM events WHERE team_id = %(team_id)s {query}", + {"team_id": team.pk, **params}, + ) + ] ) - expected = list(sorted([test_events[index] for index in expected_event_indexes])) + expected = sorted([test_events[index] for index in expected_event_indexes]) assert uuids == expected @@ -1837,18 +1833,16 @@ def test_prop_filter_json_extract_person_on_events_materialized( ) assert "JSON" not in query - uuids = list( - sorted( - [ - str(uuid) - for (uuid,) in sync_execute( - f"SELECT uuid FROM events WHERE team_id = %(team_id)s {query}", - {"team_id": team.pk, **params}, - ) - ] - ) + uuids = sorted( + [ + str(uuid) + for (uuid,) in sync_execute( + f"SELECT uuid FROM events WHERE team_id = %(team_id)s {query}", + {"team_id": team.pk, **params}, + ) + ] ) - expected = list(sorted([test_events[index] for index in expected_event_indexes])) + expected = sorted([test_events[index] for index in expected_event_indexes]) assert uuids == expected diff --git a/ee/clickhouse/queries/column_optimizer.py b/ee/clickhouse/queries/column_optimizer.py index 330830f1c2288..dd62154dd2037 100644 --- a/ee/clickhouse/queries/column_optimizer.py +++ b/ee/clickhouse/queries/column_optimizer.py @@ -22,7 +22,7 @@ class EnterpriseColumnOptimizer(FOSSColumnOptimizer): @cached_property def group_types_to_query(self) -> Set[GroupTypeIndex]: used_properties = self.used_properties_with_type("group") - return set(cast(GroupTypeIndex, group_type_index) for _, _, group_type_index in used_properties) + return {cast(GroupTypeIndex, group_type_index) for _, _, group_type_index in used_properties} @cached_property def group_on_event_columns_to_query(self) -> Set[ColumnName]: diff --git a/ee/clickhouse/queries/event_query.py b/ee/clickhouse/queries/event_query.py index 3e57be3e3892f..13a2191c4e779 100644 --- a/ee/clickhouse/queries/event_query.py +++ b/ee/clickhouse/queries/event_query.py @@ -33,13 +33,19 @@ def __init__( should_join_distinct_ids=False, should_join_persons=False, # Extra events/person table columns to fetch since parent query needs them - extra_fields: List[ColumnName] = [], - extra_event_properties: List[PropertyName] = [], - extra_person_fields: List[ColumnName] = [], + extra_fields: List[ColumnName] = None, + extra_event_properties: List[PropertyName] = None, + extra_person_fields: List[ColumnName] = None, override_aggregate_users_by_distinct_id: Optional[bool] = None, person_on_events_mode: PersonOnEventsMode = PersonOnEventsMode.DISABLED, **kwargs, ) -> None: + if extra_person_fields is None: + extra_person_fields = [] + if extra_event_properties is None: + extra_event_properties = [] + if extra_fields is None: + extra_fields = [] super().__init__( filter=filter, team=team, diff --git a/ee/clickhouse/queries/experiments/utils.py b/ee/clickhouse/queries/experiments/utils.py index 1a11df125c4ce..88418e3e354d2 100644 --- a/ee/clickhouse/queries/experiments/utils.py +++ b/ee/clickhouse/queries/experiments/utils.py @@ -31,7 +31,7 @@ def requires_flag_warning(filter: Filter, team: Team) -> bool: events.add(entity.id) entity_query = f"AND event IN %(events_list)s" - entity_params = {"events_list": sorted(list(events))} + entity_params = {"events_list": sorted(events)} events_result = sync_execute( f""" diff --git a/ee/clickhouse/queries/funnels/funnel_correlation.py b/ee/clickhouse/queries/funnels/funnel_correlation.py index 00ebb685dc416..4dc2b50a39490 100644 --- a/ee/clickhouse/queries/funnels/funnel_correlation.py +++ b/ee/clickhouse/queries/funnels/funnel_correlation.py @@ -587,7 +587,7 @@ def _get_funnel_step_names(self): elif entity.id is not None: events.add(entity.id) - return sorted(list(events)) + return sorted(events) def _run(self) -> Tuple[List[EventOddsRatio], bool]: """ diff --git a/ee/clickhouse/queries/test/test_cohort_query.py b/ee/clickhouse/queries/test/test_cohort_query.py index 6b9d4cf7ce116..c88612a118a6b 100644 --- a/ee/clickhouse/queries/test/test_cohort_query.py +++ b/ee/clickhouse/queries/test/test_cohort_query.py @@ -26,8 +26,10 @@ def _make_event_sequence( interval_days, period_event_counts, event="$pageview", - properties={}, + properties=None, ): + if properties is None: + properties = {} for period_index, event_count in enumerate(period_event_counts): for i in range(event_count): _create_event( diff --git a/ee/migrations/0012_migrate_tags_v2.py b/ee/migrations/0012_migrate_tags_v2.py index c7e325225ec41..9a2cf8e3d39c4 100644 --- a/ee/migrations/0012_migrate_tags_v2.py +++ b/ee/migrations/0012_migrate_tags_v2.py @@ -40,7 +40,7 @@ def forwards(apps, schema_editor): ) event_definitions = iter(event_definition_paginator.get_page(event_definition_page)) for tags, team_id, event_definition_id in event_definitions: - unique_tags = set(tagify(t) for t in tags if isinstance(t, str) and t.strip() != "") + unique_tags = {tagify(t) for t in tags if isinstance(t, str) and t.strip() != ""} for tag in unique_tags: temp_tag = Tag(name=tag, team_id=team_id) createables.append( @@ -71,7 +71,7 @@ def forwards(apps, schema_editor): ) property_definitions = iter(property_definition_paginator.get_page(property_definition_page)) for tags, team_id, property_definition_id in property_definitions: - unique_tags = set(tagify(t) for t in tags if isinstance(t, str) and t.strip() != "") + unique_tags = {tagify(t) for t in tags if isinstance(t, str) and t.strip() != ""} for tag in unique_tags: temp_tag = Tag(name=tag, team_id=team_id) createables.append( diff --git a/ee/tasks/test/subscriptions/subscriptions_test_factory.py b/ee/tasks/test/subscriptions/subscriptions_test_factory.py index ef459c44e981a..cbe268b76e9e8 100644 --- a/ee/tasks/test/subscriptions/subscriptions_test_factory.py +++ b/ee/tasks/test/subscriptions/subscriptions_test_factory.py @@ -7,13 +7,13 @@ def create_subscription(**kwargs: Any) -> Subscription: - payload = dict( - target_type="email", - target_value="test1@posthog.com,test2@posthog.com", - frequency="daily", - interval=1, - start_date=datetime(2022, 1, 1, 9, 0).replace(tzinfo=ZoneInfo("UTC")), - ) + payload = { + "target_type": "email", + "target_value": "test1@posthog.com,test2@posthog.com", + "frequency": "daily", + "interval": 1, + "start_date": datetime(2022, 1, 1, 9, 0).replace(tzinfo=ZoneInfo("UTC")), + } payload.update(kwargs) return Subscription.objects.create(**payload) diff --git a/posthog/api/documentation.py b/posthog/api/documentation.py index 91b4851a471b9..47820a9cb2203 100644 --- a/posthog/api/documentation.py +++ b/posthog/api/documentation.py @@ -250,5 +250,5 @@ def custom_postprocessing_hook(result, generator, request, public): **result, "info": {"title": "PostHog API", "version": None, "description": ""}, "paths": paths, - "x-tagGroups": [{"name": "All endpoints", "tags": sorted(list(set(all_tags)))}], + "x-tagGroups": [{"name": "All endpoints", "tags": sorted(set(all_tags))}], } diff --git a/posthog/api/ingestion_warnings.py b/posthog/api/ingestion_warnings.py index 4c6ce6acdd8b9..c246d990d61e2 100644 --- a/posthog/api/ingestion_warnings.py +++ b/posthog/api/ingestion_warnings.py @@ -47,4 +47,4 @@ def _calculate_summaries(warning_events): summaries[warning_type]["warnings"].append({"type": warning_type, "timestamp": timestamp, "details": details}) summaries[warning_type]["count"] += 1 - return list(sorted(summaries.values(), key=lambda summary: summary["lastSeen"], reverse=True)) + return sorted(summaries.values(), key=lambda summary: summary["lastSeen"], reverse=True) diff --git a/posthog/api/plugin.py b/posthog/api/plugin.py index 55ab950af2958..f6a60f67b12b4 100644 --- a/posthog/api/plugin.py +++ b/posthog/api/plugin.py @@ -63,7 +63,11 @@ def _update_plugin_attachments(request: request.Request, plugin_config: PluginCo _update_plugin_attachment(request, plugin_config, match.group(1), None, user) -def get_plugin_config_changes(old_config: Dict[str, Any], new_config: Dict[str, Any], secret_fields=[]) -> List[Change]: +def get_plugin_config_changes( + old_config: Dict[str, Any], new_config: Dict[str, Any], secret_fields=None +) -> List[Change]: + if secret_fields is None: + secret_fields = [] config_changes = dict_changes_between("Plugin", old_config, new_config) for i, change in enumerate(config_changes): @@ -79,8 +83,10 @@ def get_plugin_config_changes(old_config: Dict[str, Any], new_config: Dict[str, def log_enabled_change_activity( - new_plugin_config: PluginConfig, old_enabled: bool, user: User, was_impersonated: bool, changes=[] + new_plugin_config: PluginConfig, old_enabled: bool, user: User, was_impersonated: bool, changes=None ): + if changes is None: + changes = [] if old_enabled != new_plugin_config.enabled: log_activity( organization_id=new_plugin_config.team.organization.id, diff --git a/posthog/api/sharing.py b/posthog/api/sharing.py index d3794d050f6db..c7ab40fb0f89d 100644 --- a/posthog/api/sharing.py +++ b/posthog/api/sharing.py @@ -122,12 +122,12 @@ def _get_sharing_configuration(self, context: Dict[str, Any]): insight = context.get("insight") recording = context.get("recording") - config_kwargs = dict( - team_id=self.team_id, - insight=insight, - dashboard=dashboard, - recording=recording, - ) + config_kwargs = { + "team_id": self.team_id, + "insight": insight, + "dashboard": dashboard, + "recording": recording, + } try: instance = SharingConfiguration.objects.get(**config_kwargs) diff --git a/posthog/api/test/dashboards/test_dashboard.py b/posthog/api/test/dashboards/test_dashboard.py index 0508b750f69ff..1f7cd4b533fbd 100644 --- a/posthog/api/test/dashboards/test_dashboard.py +++ b/posthog/api/test/dashboards/test_dashboard.py @@ -903,7 +903,7 @@ def test_dashboard_duplication(self): self.assertEqual(len(response["tiles"]), len(existing_dashboard.insights.all())) existing_dashboard_item_id_set = {tile1.pk, tile2.pk} - response_item_id_set = set(map(lambda x: x.get("id", None), response["tiles"])) + response_item_id_set = {x.get("id", None) for x in response["tiles"]} # check both sets are disjoint to verify that the new items' ids are different than the existing items self.assertTrue(existing_dashboard_item_id_set.isdisjoint(response_item_id_set)) diff --git a/posthog/api/test/dashboards/test_dashboard_text_tiles.py b/posthog/api/test/dashboards/test_dashboard_text_tiles.py index 3bf802f18be6b..34b9366da5aeb 100644 --- a/posthog/api/test/dashboards/test_dashboard_text_tiles.py +++ b/posthog/api/test/dashboards/test_dashboard_text_tiles.py @@ -164,7 +164,7 @@ def test_can_update_a_single_text_tile_color(self) -> None: dashboard_id, dashboard_json = self.dashboard_api.update_text_tile(dashboard_id, updated_tile) assert len(dashboard_json["tiles"]) == 2 - assert set((t["id"], t["color"]) for t in dashboard_json["tiles"]) == { + assert {(t["id"], t["color"]) for t in dashboard_json["tiles"]} == { (tile_ids[0], "purple"), (tile_ids[1], None), } diff --git a/posthog/api/test/test_capture.py b/posthog/api/test/test_capture.py index 2a80186082dea..9e284b4606c60 100644 --- a/posthog/api/test/test_capture.py +++ b/posthog/api/test/test_capture.py @@ -187,7 +187,7 @@ def _to_arguments(self, patch_process_event_with_plugins: Any) -> dict: def _send_original_version_session_recording_event( self, number_of_events: int = 1, - event_data: Dict | None = {}, + event_data: Dict | None = None, snapshot_source=3, snapshot_type=1, session_id="abc123", @@ -197,6 +197,8 @@ def _send_original_version_session_recording_event( ) -> dict: if event_data is None: event_data = {} + if event_data is None: + event_data = {} event = { "event": "$snapshot", diff --git a/posthog/api/test/test_comments.py b/posthog/api/test/test_comments.py index 42ede7a56587b..6807c924cbbf1 100644 --- a/posthog/api/test/test_comments.py +++ b/posthog/api/test/test_comments.py @@ -7,7 +7,9 @@ class TestComments(APIBaseTest, QueryMatchingTest): - def _create_comment(self, data={}) -> Any: + def _create_comment(self, data=None) -> Any: + if data is None: + data = {} payload = { "content": "my content", "scope": "Notebook", diff --git a/posthog/api/test/test_decide.py b/posthog/api/test/test_decide.py index e56d763ed869f..241b45d02daad 100644 --- a/posthog/api/test/test_decide.py +++ b/posthog/api/test/test_decide.py @@ -73,12 +73,14 @@ def _post_decide( origin="http://127.0.0.1:8000", api_version=1, distinct_id="example_id", - groups={}, + groups=None, geoip_disable=False, ip="127.0.0.1", disable_flags=False, user_agent: Optional[str] = None, ): + if groups is None: + groups = {} return self.client.post( f"/decide/?v={api_version}", { @@ -3322,10 +3324,12 @@ def _post_decide( origin="http://127.0.0.1:8000", api_version=1, distinct_id="example_id", - groups={}, + groups=None, geoip_disable=False, ip="127.0.0.1", ): + if groups is None: + groups = {} return self.client.post( f"/decide/?v={api_version}", { @@ -3557,11 +3561,15 @@ def _post_decide( origin="http://127.0.0.1:8000", api_version=3, distinct_id="example_id", - groups={}, - person_props={}, + groups=None, + person_props=None, geoip_disable=False, ip="127.0.0.1", ): + if person_props is None: + person_props = {} + if groups is None: + groups = {} return self.client.post( f"/decide/?v={api_version}", { diff --git a/posthog/api/test/test_feature_flag.py b/posthog/api/test/test_feature_flag.py index ea7c13810ca03..8a6010bbed37e 100644 --- a/posthog/api/test/test_feature_flag.py +++ b/posthog/api/test/test_feature_flag.py @@ -1327,7 +1327,7 @@ def test_create_feature_flag_usage_dashboard(self, mock_capture): self.assertEqual(instance.key, "alpha-feature") dashboard = instance.usage_dashboard - tiles = sorted([tile for tile in dashboard.tiles.all()], key=lambda x: x.insight.name) + tiles = sorted(dashboard.tiles.all(), key=lambda x: x.insight.name) self.assertEqual(dashboard.name, "Generated Dashboard: alpha-feature Usage") self.assertEqual( @@ -1421,7 +1421,7 @@ def test_create_feature_flag_usage_dashboard(self, mock_capture): instance.refresh_from_db() dashboard = instance.usage_dashboard - tiles = sorted([tile for tile in dashboard.tiles.all()], key=lambda x: x.insight.name) + tiles = sorted(dashboard.tiles.all(), key=lambda x: x.insight.name) self.assertEqual(dashboard.name, "Generated Dashboard: alpha-feature Usage") self.assertEqual( diff --git a/posthog/api/test/test_organization_feature_flag.py b/posthog/api/test/test_organization_feature_flag.py index 90576b688aa75..41960032ca8b7 100644 --- a/posthog/api/test/test_organization_feature_flag.py +++ b/posthog/api/test/test_organization_feature_flag.py @@ -606,7 +606,7 @@ def connect(parent, child): original_cohorts_cache = {} for _, cohort in cohorts.items(): original_cohorts_cache[cohort.id] = cohort - original_cohort_ids = {cohort_id for cohort_id in original_cohorts_cache.keys()} + original_cohort_ids = set(original_cohorts_cache.keys()) topologically_sorted_original_cohort_ids = sort_cohorts_topologically( original_cohort_ids, original_cohorts_cache ) diff --git a/posthog/api/test/test_plugin.py b/posthog/api/test/test_plugin.py index b66944c0acc07..16e0fc4c0d1d0 100644 --- a/posthog/api/test/test_plugin.py +++ b/posthog/api/test/test_plugin.py @@ -804,7 +804,7 @@ def test_transpile_plugin_frontend_source(self, mock_get, mock_reload): ) try: PluginSourceFile.objects.get(plugin_id=id) - assert False, "Should have thrown DoesNotExist" + raise AssertionError("Should have thrown DoesNotExist") except PluginSourceFile.DoesNotExist: assert True diff --git a/posthog/api/test/test_preflight.py b/posthog/api/test/test_preflight.py index d5fec0c360ff7..2b7d6986d7e7c 100644 --- a/posthog/api/test/test_preflight.py +++ b/posthog/api/test/test_preflight.py @@ -19,7 +19,9 @@ class TestPreflight(APIBaseTest, QueryMatchingTest): def instance_preferences(self, **kwargs): return {"debug_queries": False, "disable_paid_fs": False, **kwargs} - def preflight_dict(self, options={}): + def preflight_dict(self, options=None): + if options is None: + options = {} return { "django": True, "redis": True, @@ -46,7 +48,9 @@ def preflight_dict(self, options={}): **options, } - def preflight_authenticated_dict(self, options={}): + def preflight_authenticated_dict(self, options=None): + if options is None: + options = {} preflight = { "opt_out_capture": False, "licensed_users_available": None, diff --git a/posthog/api/utils.py b/posthog/api/utils.py index 75373856ccd56..d85c5e1efbe93 100644 --- a/posthog/api/utils.py +++ b/posthog/api/utils.py @@ -251,8 +251,10 @@ def create_event_definitions_sql( event_type: EventDefinitionType, is_enterprise: bool = False, conditions: str = "", - order_expressions: List[Tuple[str, Literal["ASC", "DESC"]]] = [], + order_expressions: List[Tuple[str, Literal["ASC", "DESC"]]] = None, ) -> str: + if order_expressions is None: + order_expressions = [] if is_enterprise: from ee.models import EnterpriseEventDefinition diff --git a/posthog/async_migrations/migrations/0002_events_sample_by.py b/posthog/async_migrations/migrations/0002_events_sample_by.py index 7ad43de2934a3..7038975b2afbb 100644 --- a/posthog/async_migrations/migrations/0002_events_sample_by.py +++ b/posthog/async_migrations/migrations/0002_events_sample_by.py @@ -186,13 +186,11 @@ def healthcheck(self): @cached_property def _partitions(self): - return list( - sorted( - row[0] - for row in sync_execute( - f"SELECT DISTINCT toUInt32(partition) FROM system.parts WHERE database = %(database)s AND table='{EVENTS_TABLE}'", - {"database": CLICKHOUSE_DATABASE}, - ) + return sorted( + row[0] + for row in sync_execute( + f"SELECT DISTINCT toUInt32(partition) FROM system.parts WHERE database = %(database)s AND table='{EVENTS_TABLE}'", + {"database": CLICKHOUSE_DATABASE}, ) ) diff --git a/posthog/async_migrations/migrations/0003_fill_person_distinct_id2.py b/posthog/async_migrations/migrations/0003_fill_person_distinct_id2.py index ba1d6dd917292..697cf7e21e3c6 100644 --- a/posthog/async_migrations/migrations/0003_fill_person_distinct_id2.py +++ b/posthog/async_migrations/migrations/0003_fill_person_distinct_id2.py @@ -91,4 +91,4 @@ def migrate_team_operation(self, team_id: int): @cached_property def _team_ids(self): - return list(sorted(row[0] for row in sync_execute("SELECT DISTINCT team_id FROM person_distinct_id"))) + return sorted(row[0] for row in sync_execute("SELECT DISTINCT team_id FROM person_distinct_id")) diff --git a/posthog/async_migrations/setup.py b/posthog/async_migrations/setup.py index fff7205a4c8e0..4493f137bd2a2 100644 --- a/posthog/async_migrations/setup.py +++ b/posthog/async_migrations/setup.py @@ -42,7 +42,7 @@ def setup_async_migrations(ignore_posthog_version: bool = False): 4. Populate a dependencies map and in-memory record of migration definitions """ - applied_migrations = set(instance.name for instance in get_all_completed_async_migrations()) + applied_migrations = {instance.name for instance in get_all_completed_async_migrations()} unapplied_migrations = set(ALL_ASYNC_MIGRATIONS.keys()) - applied_migrations for migration_name, migration in ALL_ASYNC_MIGRATIONS.items(): diff --git a/posthog/batch_exports/models.py b/posthog/batch_exports/models.py index 70b85c4d35bde..abe17420d45c9 100644 --- a/posthog/batch_exports/models.py +++ b/posthog/batch_exports/models.py @@ -227,9 +227,11 @@ def fetch_batch_export_log_entries( before: dt.datetime | None = None, search: str | None = None, limit: int | None = None, - level_filter: list[BatchExportLogEntryLevel] = [], + level_filter: list[BatchExportLogEntryLevel] = None, ) -> list[BatchExportLogEntry]: """Fetch a list of batch export log entries from ClickHouse.""" + if level_filter is None: + level_filter = [] clickhouse_where_parts: list[str] = [] clickhouse_kwargs: dict[str, typing.Any] = {} diff --git a/posthog/batch_exports/service.py b/posthog/batch_exports/service.py index c26be9a77ed1a..8c9784f0638ae 100644 --- a/posthog/batch_exports/service.py +++ b/posthog/batch_exports/service.py @@ -463,7 +463,7 @@ def sync_batch_export(batch_export: BatchExport, created: bool): paused=batch_export.paused, ) - destination_config_fields = set(field.name for field in fields(workflow_inputs)) + destination_config_fields = {field.name for field in fields(workflow_inputs)} destination_config = {k: v for k, v in batch_export.destination.config.items() if k in destination_config_fields} temporal = sync_connect() diff --git a/posthog/caching/test/test_insight_cache.py b/posthog/caching/test/test_insight_cache.py index 88495a795695e..269aebf887838 100644 --- a/posthog/caching/test/test_insight_cache.py +++ b/posthog/caching/test/test_insight_cache.py @@ -54,7 +54,7 @@ def create_insight_caching_state( # Reaching into the internals of LocMemCache def cache_keys(cache): - return set(key.split(":", 2)[-1] for key in cache._cache.keys()) + return {key.split(":", 2)[-1] for key in cache._cache.keys()} @pytest.mark.django_db diff --git a/posthog/caching/utils.py b/posthog/caching/utils.py index 636fdbb19c53e..d0c6450cc7dba 100644 --- a/posthog/caching/utils.py +++ b/posthog/caching/utils.py @@ -58,12 +58,12 @@ def active_teams() -> Set[int]: return set() redis.zadd( RECENTLY_ACCESSED_TEAMS_REDIS_KEY, - {team: score for team, score in teams_by_recency}, + dict(teams_by_recency), ) redis.expire(RECENTLY_ACCESSED_TEAMS_REDIS_KEY, IN_A_DAY) all_teams = teams_by_recency - return set(int(team_id) for team_id, _ in all_teams) + return {int(team_id) for team_id, _ in all_teams} def stale_cache_invalidation_disabled(team: Team) -> bool: diff --git a/posthog/clickhouse/client/migration_tools.py b/posthog/clickhouse/client/migration_tools.py index 0d105b0423972..f71abd489fd64 100644 --- a/posthog/clickhouse/client/migration_tools.py +++ b/posthog/clickhouse/client/migration_tools.py @@ -5,11 +5,14 @@ from posthog.clickhouse.client.execute import sync_execute -def run_sql_with_exceptions(sql: Union[str, Callable[[], str]], settings={}): +def run_sql_with_exceptions(sql: Union[str, Callable[[], str]], settings=None): """ migrations.RunSQL does not raise exceptions, so we need to wrap it in a function that does. """ + if settings is None: + settings = {} + def run_sql(database): nonlocal sql if callable(sql): diff --git a/posthog/clickhouse/system_status.py b/posthog/clickhouse/system_status.py index bd9bd22f427c6..e04c6bf7597f1 100644 --- a/posthog/clickhouse/system_status.py +++ b/posthog/clickhouse/system_status.py @@ -122,7 +122,7 @@ def system_status() -> Generator[SystemStatusRow, None, None]: "value": "", "subrows": { "columns": ["Metric", "Value", "Description"], - "rows": list(sorted(system_metrics)), + "rows": sorted(system_metrics), }, } diff --git a/posthog/demo/matrix/taxonomy_inference.py b/posthog/demo/matrix/taxonomy_inference.py index f9860a9f9325a..cc5686de96b0b 100644 --- a/posthog/demo/matrix/taxonomy_inference.py +++ b/posthog/demo/matrix/taxonomy_inference.py @@ -58,7 +58,7 @@ def infer_taxonomy_for_team(team_id: int) -> Tuple[int, int, int]: def _get_events_last_seen_at(team_id: int) -> Dict[str, timezone.datetime]: from posthog.client import sync_execute - return {event: last_seen_at for event, last_seen_at in sync_execute(_GET_EVENTS_LAST_SEEN_AT, {"team_id": team_id})} + return dict(sync_execute(_GET_EVENTS_LAST_SEEN_AT, {"team_id": team_id})) def _get_property_types(team_id: int) -> Dict[str, Optional[PropertyType]]: diff --git a/posthog/email.py b/posthog/email.py index ccdc2f9ae6d02..3220e65204b4f 100644 --- a/posthog/email.py +++ b/posthog/email.py @@ -42,13 +42,13 @@ def is_email_available(with_absolute_urls: bool = False) -> bool: ) -EMAIL_TASK_KWARGS = dict( - queue=CeleryQueue.EMAIL.value, - ignore_result=True, - autoretry_for=(Exception,), - max_retries=3, - retry_backoff=True, -) +EMAIL_TASK_KWARGS = { + "queue": CeleryQueue.EMAIL.value, + "ignore_result": True, + "autoretry_for": (Exception,), + "max_retries": 3, + "retry_backoff": True, +} @shared_task(**EMAIL_TASK_KWARGS) @@ -135,10 +135,12 @@ def __init__( campaign_key: str, subject: str, template_name: str, - template_context: Dict = {}, + template_context: Dict = None, headers: Optional[Dict] = None, reply_to: Optional[str] = None, ): + if template_context is None: + template_context = {} if not is_email_available(): raise exceptions.ImproperlyConfigured("Email is not enabled in this instance.") diff --git a/posthog/event_usage.py b/posthog/event_usage.py index e1f7f48dcb421..4fa82d70a2183 100644 --- a/posthog/event_usage.py +++ b/posthog/event_usage.py @@ -217,7 +217,9 @@ def report_user_organization_membership_level_changed( ) -def report_user_action(user: User, event: str, properties: Dict = {}, team: Optional[Team] = None): +def report_user_action(user: User, event: str, properties: Dict = None, team: Optional[Team] = None): + if properties is None: + properties = {} posthoganalytics.capture( user.distinct_id, event, @@ -252,12 +254,14 @@ def groups(organization: Optional[Organization] = None, team: Optional[Team] = N def report_team_action( team: Team, event: str, - properties: Dict = {}, + properties: Dict = None, group_properties: Optional[Dict] = None, ): """ For capturing events where it is unclear which user was the core actor we can use the team instead """ + if properties is None: + properties = {} posthoganalytics.capture(str(team.uuid), event, properties=properties, groups=groups(team=team)) if group_properties: @@ -267,12 +271,14 @@ def report_team_action( def report_organization_action( organization: Organization, event: str, - properties: Dict = {}, + properties: Dict = None, group_properties: Optional[Dict] = None, ): """ For capturing events where it is unclear which user was the core actor we can use the organization instead """ + if properties is None: + properties = {} posthoganalytics.capture( str(organization.id), event, diff --git a/posthog/helpers/tests/test_multi_property_breakdown.py b/posthog/helpers/tests/test_multi_property_breakdown.py index cc2dad4bbc57f..d22675adf84e9 100644 --- a/posthog/helpers/tests/test_multi_property_breakdown.py +++ b/posthog/helpers/tests/test_multi_property_breakdown.py @@ -14,7 +14,7 @@ def test_handles_empty_inputs(self): try: protect_old_clients_from_multi_property_default(data, result) except KeyError: - assert False, "should not raise any KeyError" + raise AssertionError("should not raise any KeyError") def test_handles_empty_breakdowns_array(self): data: Dict[str, Any] = { @@ -27,7 +27,7 @@ def test_handles_empty_breakdowns_array(self): try: protect_old_clients_from_multi_property_default(data, result) except KeyError: - assert False, "should not raise any KeyError" + raise AssertionError("should not raise any KeyError") def test_keeps_multi_property_breakdown_for_multi_property_requests(self): data: Dict[str, Any] = { diff --git a/posthog/hogql/resolver.py b/posthog/hogql/resolver.py index 19bbddb9f65b7..964cb1adde46d 100644 --- a/posthog/hogql/resolver.py +++ b/posthog/hogql/resolver.py @@ -38,7 +38,7 @@ def resolve_constant_data_type(constant: Any) -> ConstantType: if isinstance(constant, str): return ast.StringType() if isinstance(constant, list): - unique_types = set(str(resolve_constant_data_type(item)) for item in constant) + unique_types = {str(resolve_constant_data_type(item)) for item in constant} return ast.ArrayType( item_type=resolve_constant_data_type(constant[0]) if len(unique_types) == 1 else ast.UnknownType() ) diff --git a/posthog/hogql/test/test_query.py b/posthog/hogql/test/test_query.py index 61f5d839919aa..9d781b552b92f 100644 --- a/posthog/hogql/test/test_query.py +++ b/posthog/hogql/test/test_query.py @@ -1014,7 +1014,7 @@ def test_property_access_with_arrays(self): f"LIMIT 100 " f"SETTINGS readonly=2, max_execution_time=60, allow_experimental_object_type=1", ) - self.assertEqual(response.results[0], tuple(map(lambda x: random_uuid, alternatives))) + self.assertEqual(response.results[0], tuple((random_uuid for x in alternatives))) def test_property_access_with_arrays_zero_index_error(self): query = f"SELECT properties.something[0] FROM events" diff --git a/posthog/hogql/transforms/lazy_tables.py b/posthog/hogql/transforms/lazy_tables.py index bdbb322d54397..027fe1e36337c 100644 --- a/posthog/hogql/transforms/lazy_tables.py +++ b/posthog/hogql/transforms/lazy_tables.py @@ -211,7 +211,7 @@ def visit_select_query(self, node: ast.SelectQuery): if property is not None: chain.extend(property.chain) property.joined_subquery_field_name = ( - f"{field.name}___{'___'.join(map(lambda x: str(x), property.chain))}" + f"{field.name}___{'___'.join((str(x) for x in property.chain))}" ) new_join.fields_accessed[property.joined_subquery_field_name] = chain else: @@ -230,7 +230,7 @@ def visit_select_query(self, node: ast.SelectQuery): if property is not None: chain.extend(property.chain) property.joined_subquery_field_name = ( - f"{field.name}___{'___'.join(map(lambda x: str(x), property.chain))}" + f"{field.name}___{'___'.join((str(x) for x in property.chain))}" ) new_table.fields_accessed[property.joined_subquery_field_name] = chain else: @@ -253,7 +253,7 @@ def visit_select_query(self, node: ast.SelectQuery): if property is not None: chain.extend(property.chain) property.joined_subquery_field_name = ( - f"{field.name}___{'___'.join(map(lambda x: str(x), property.chain))}" + f"{field.name}___{'___'.join((str(x) for x in property.chain))}" ) new_join.fields_accessed[property.joined_subquery_field_name] = chain else: @@ -272,7 +272,7 @@ def visit_select_query(self, node: ast.SelectQuery): if property is not None: chain.extend(property.chain) property.joined_subquery_field_name = ( - f"{field.name}___{'___'.join(map(lambda x: str(x), property.chain))}" + f"{field.name}___{'___'.join((str(x) for x in property.chain))}" ) new_table.fields_accessed[property.joined_subquery_field_name] = chain else: @@ -283,7 +283,7 @@ def visit_select_query(self, node: ast.SelectQuery): join_constraint_overrides: Dict[str, List[ConstraintOverride]] = {} def create_override(table_name: str, field_chain: List[str | int]) -> None: - alias = f"{table_name}___{'___'.join(map(lambda x: str(x), field_chain))}" + alias = f"{table_name}___{'___'.join((str(x) for x in field_chain))}" if table_name in tables_to_add: tables_to_add[table_name].fields_accessed[alias] = field_chain diff --git a/posthog/hogql/visitor.py b/posthog/hogql/visitor.py index c11856169297f..7dabdd3e543ee 100644 --- a/posthog/hogql/visitor.py +++ b/posthog/hogql/visitor.py @@ -367,7 +367,7 @@ def visit_lambda(self, node: ast.Lambda): start=None if self.clear_locations else node.start, end=None if self.clear_locations else node.end, type=None if self.clear_types else node.type, - args=[arg for arg in node.args], + args=list(node.args), expr=self.visit(node.expr), ) diff --git a/posthog/hogql_queries/actors_query_runner.py b/posthog/hogql_queries/actors_query_runner.py index 93e9f40c70739..92b8f27811505 100644 --- a/posthog/hogql_queries/actors_query_runner.py +++ b/posthog/hogql_queries/actors_query_runner.py @@ -42,7 +42,7 @@ def determine_strategy(self) -> ActorStrategy: def get_recordings(self, event_results, recordings_lookup) -> Generator[dict, None, None]: return ( {"session_id": session_id, "events": recordings_lookup[session_id]} - for session_id in set(event[2] for event in event_results) + for session_id in {event[2] for event in event_results} if session_id in recordings_lookup ) diff --git a/posthog/hogql_queries/events_query_runner.py b/posthog/hogql_queries/events_query_runner.py index b97fc06ab9d24..9bb289b684776 100644 --- a/posthog/hogql_queries/events_query_runner.py +++ b/posthog/hogql_queries/events_query_runner.py @@ -219,7 +219,7 @@ def calculate(self) -> EventsQueryResponse: with self.timings.measure("person_column_extra_query"): # Make a query into postgres to fetch person person_idx = person_indices[0] - distinct_ids = list(set(event[person_idx] for event in self.paginator.results)) + distinct_ids = list({event[person_idx] for event in self.paginator.results}) persons = get_persons_by_distinct_ids(self.team.pk, distinct_ids) persons = persons.prefetch_related(Prefetch("persondistinctid_set", to_attr="distinct_ids_cache")) distinct_to_person: Dict[str, Person] = {} diff --git a/posthog/hogql_queries/insights/funnels/base.py b/posthog/hogql_queries/insights/funnels/base.py index 5d84328d2063d..830f26038480a 100644 --- a/posthog/hogql_queries/insights/funnels/base.py +++ b/posthog/hogql_queries/insights/funnels/base.py @@ -648,7 +648,7 @@ def _get_funnel_person_step_condition(self) -> ast.Expr: conditions.append(parse_expr(f"steps IN {funnelCustomSteps}")) elif funnelStep is not None: if funnelStep >= 0: - step_nums = [i for i in range(funnelStep, max_steps + 1)] + step_nums = list(range(funnelStep, max_steps + 1)) conditions.append(parse_expr(f"steps IN {step_nums}")) else: step_num = abs(funnelStep) - 1 diff --git a/posthog/hogql_queries/insights/funnels/funnel_correlation_query_runner.py b/posthog/hogql_queries/insights/funnels/funnel_correlation_query_runner.py index 945a1b7da5cce..bcead7bbb8c89 100644 --- a/posthog/hogql_queries/insights/funnels/funnel_correlation_query_runner.py +++ b/posthog/hogql_queries/insights/funnels/funnel_correlation_query_runner.py @@ -831,7 +831,7 @@ def _get_funnel_step_names(self) -> List[str]: else: raise ValidationError("Data warehouse nodes are not supported here") - return sorted(list(events)) + return sorted(events) @property def properties_to_include(self) -> List[str]: diff --git a/posthog/hogql_queries/insights/funnels/funnel_event_query.py b/posthog/hogql_queries/insights/funnels/funnel_event_query.py index f2d0e115e2d0b..b525e71da734b 100644 --- a/posthog/hogql_queries/insights/funnels/funnel_event_query.py +++ b/posthog/hogql_queries/insights/funnels/funnel_event_query.py @@ -21,9 +21,13 @@ class FunnelEventQuery: def __init__( self, context: FunnelQueryContext, - extra_fields: List[ColumnName] = [], - extra_event_properties: List[PropertyName] = [], + extra_fields: List[ColumnName] = None, + extra_event_properties: List[PropertyName] = None, ): + if extra_event_properties is None: + extra_event_properties = [] + if extra_fields is None: + extra_fields = [] self.context = context self._extra_fields = extra_fields diff --git a/posthog/hogql_queries/insights/funnels/test/breakdown_cases.py b/posthog/hogql_queries/insights/funnels/test/breakdown_cases.py index 4d00b0a265b98..db5e882963e9f 100644 --- a/posthog/hogql_queries/insights/funnels/test/breakdown_cases.py +++ b/posthog/hogql_queries/insights/funnels/test/breakdown_cases.py @@ -3068,7 +3068,7 @@ def test_funnel_aggregate_by_groups_breakdown_group_person_on_events(self): def sort_breakdown_funnel_results(results: List[Dict[int, Any]]): - return list(sorted(results, key=lambda r: r[0]["breakdown_value"])) + return sorted(results, key=lambda r: r[0]["breakdown_value"]) def assert_funnel_results_equal(left: List[Dict[str, Any]], right: List[Dict[str, Any]]): diff --git a/posthog/hogql_queries/insights/funnels/test/test_funnel_breakdowns_by_current_url.py b/posthog/hogql_queries/insights/funnels/test/test_funnel_breakdowns_by_current_url.py index b745ea87761eb..946806be2c88e 100644 --- a/posthog/hogql_queries/insights/funnels/test/test_funnel_breakdowns_by_current_url.py +++ b/posthog/hogql_queries/insights/funnels/test/test_funnel_breakdowns_by_current_url.py @@ -116,7 +116,11 @@ def setUp(self): journeys_for(journey, team=self.team, create_people=True) - def _run(self, extra: Dict = {}, events_extra: Dict = {}): + def _run(self, extra: Dict = None, events_extra: Dict = None): + if events_extra is None: + events_extra = {} + if extra is None: + extra = {} filters = { "events": [ { diff --git a/posthog/hogql_queries/insights/test/test_insight_actors_query_runner.py b/posthog/hogql_queries/insights/test/test_insight_actors_query_runner.py index d24e4d6d8f2b7..c9e6b578e0e9d 100644 --- a/posthog/hogql_queries/insights/test/test_insight_actors_query_runner.py +++ b/posthog/hogql_queries/insights/test/test_insight_actors_query_runner.py @@ -69,7 +69,9 @@ def _create_test_events(self): ] ) - def select(self, query: str, placeholders: Dict[str, Any] = {}): + def select(self, query: str, placeholders: Dict[str, Any] = None): + if placeholders is None: + placeholders = {} return execute_hogql_query( query=query, team=self.team, diff --git a/posthog/hogql_queries/insights/test/test_lifecycle_query_runner.py b/posthog/hogql_queries/insights/test/test_lifecycle_query_runner.py index 5a1a7440ac43b..87ef2d91a9bd2 100644 --- a/posthog/hogql_queries/insights/test/test_lifecycle_query_runner.py +++ b/posthog/hogql_queries/insights/test/test_lifecycle_query_runner.py @@ -1305,6 +1305,6 @@ def test_cohort_filter(self): def assertLifecycleResults(results, expected): sorted_results = [{"status": r["status"], "data": r["data"]} for r in sorted(results, key=lambda r: r["status"])] - sorted_expected = list(sorted(expected, key=lambda r: r["status"])) + sorted_expected = sorted(expected, key=lambda r: r["status"]) assert sorted_results == sorted_expected diff --git a/posthog/hogql_queries/insights/trends/breakdown.py b/posthog/hogql_queries/insights/trends/breakdown.py index 45a3a8421e8d8..dce6a7d0b1a49 100644 --- a/posthog/hogql_queries/insights/trends/breakdown.py +++ b/posthog/hogql_queries/insights/trends/breakdown.py @@ -218,7 +218,7 @@ def _breakdown_buckets_ast(self) -> ast.Array: # TODO: add this only if needed values.append('["",""]') - return ast.Array(exprs=list(map(lambda v: ast.Constant(value=v), values))) + return ast.Array(exprs=[ast.Constant(value=v) for v in values]) @cached_property def _breakdown_values_ast(self) -> ast.Array: diff --git a/posthog/hogql_queries/insights/trends/trends_query_runner.py b/posthog/hogql_queries/insights/trends/trends_query_runner.py index b9acb5c37d000..1a0050734ca90 100644 --- a/posthog/hogql_queries/insights/trends/trends_query_runner.py +++ b/posthog/hogql_queries/insights/trends/trends_query_runner.py @@ -646,7 +646,7 @@ def apply_formula(self, formula: str, results: List[Dict[str, Any]]) -> List[Dic group_list = list(group) if self._trends_display.should_aggregate_values(): - series_data = list(map(lambda s: [s["aggregated_value"]], group_list)) + series_data = [[s["aggregated_value"]] for s in group_list] new_series_data = FormulaAST(series_data).call(formula) new_result = group_list[0] @@ -656,7 +656,7 @@ def apply_formula(self, formula: str, results: List[Dict[str, Any]]) -> List[Dic new_result["label"] = f"Formula ({formula})" res.append(new_result) else: - series_data = list(map(lambda s: s["data"], group_list)) + series_data = [s["data"] for s in group_list] new_series_data = FormulaAST(series_data).call(formula) new_result = group_list[0] @@ -667,7 +667,7 @@ def apply_formula(self, formula: str, results: List[Dict[str, Any]]) -> List[Dic return res if self._trends_display.should_aggregate_values(): - series_data = list(map(lambda s: [s["aggregated_value"]], results)) + series_data = [[s["aggregated_value"]] for s in results] new_series_data = FormulaAST(series_data).call(formula) new_result = results[0] @@ -676,7 +676,7 @@ def apply_formula(self, formula: str, results: List[Dict[str, Any]]) -> List[Dic new_result["count"] = 0 new_result["label"] = f"Formula ({formula})" else: - series_data = list(map(lambda s: s["data"], results)) + series_data = [s["data"] for s in results] new_series_data = FormulaAST(series_data).call(formula) new_result = results[0] diff --git a/posthog/hogql_queries/test/test_events_query_runner.py b/posthog/hogql_queries/test/test_events_query_runner.py index 6237d3edc2f34..9aab4ee14a9f6 100644 --- a/posthog/hogql_queries/test/test_events_query_runner.py +++ b/posthog/hogql_queries/test/test_events_query_runner.py @@ -98,7 +98,7 @@ def test_is_not_set_boolean(self): ) ) - self.assertEqual({"p_notset", "p_null"}, set(row[0]["distinct_id"] for row in results)) + self.assertEqual({"p_notset", "p_null"}, {row[0]["distinct_id"] for row in results}) def test_is_set_boolean(self): self._create_boolean_field_test_events() @@ -112,7 +112,7 @@ def test_is_set_boolean(self): ) ) - self.assertEqual({"p_true", "p_false"}, set(row[0]["distinct_id"] for row in results)) + self.assertEqual({"p_true", "p_false"}, {row[0]["distinct_id"] for row in results}) def test_person_id_expands_to_distinct_ids(self): _create_person( diff --git a/posthog/hogql_queries/test/test_query_runner.py b/posthog/hogql_queries/test/test_query_runner.py index 8a756a8018aea..40c991ec1d038 100644 --- a/posthog/hogql_queries/test/test_query_runner.py +++ b/posthog/hogql_queries/test/test_query_runner.py @@ -29,7 +29,7 @@ class TestQueryRunner(QueryRunner): query_type: TestQuery = TestQuery # type: ignore[assignment] def calculate(self) -> QueryResponse: - return QueryResponse(results=list()) + return QueryResponse(results=[]) def _refresh_frequency(self) -> timedelta: return timedelta(minutes=4) diff --git a/posthog/management/commands/backfill_persons_and_groups_on_events.py b/posthog/management/commands/backfill_persons_and_groups_on_events.py index b7fb2fcbc46e9..0e90461a701d5 100644 --- a/posthog/management/commands/backfill_persons_and_groups_on_events.py +++ b/posthog/management/commands/backfill_persons_and_groups_on_events.py @@ -120,7 +120,9 @@ query_number = 0 -def print_and_execute_query(sql: str, name: str, dry_run: bool, timeout=180, query_args={}) -> Any: +def print_and_execute_query(sql: str, name: str, dry_run: bool, timeout=180, query_args=None) -> Any: + if query_args is None: + query_args = {} global query_number if not settings.TEST: diff --git a/posthog/management/commands/generate_demo_data.py b/posthog/management/commands/generate_demo_data.py index bae869133a455..f75f151259570 100644 --- a/posthog/management/commands/generate_demo_data.py +++ b/posthog/management/commands/generate_demo_data.py @@ -163,7 +163,7 @@ def print_results(matrix: Matrix, *, seed: str, duration: float, verbosity: int) summary_lines.append(" No events") else: assert person.first_seen_at is not None and person.last_seen_at is not None - session_count = len(set(event.properties.get("$session_id") for event in person.all_events)) + session_count = len({event.properties.get("$session_id") for event in person.all_events}) summary_lines.append( f" {event_count} event{'' if event_count == 1 else 's'} " f"across {session_count} session{'' if session_count == 1 else 's'} " diff --git a/posthog/management/commands/sync_replicated_schema.py b/posthog/management/commands/sync_replicated_schema.py index 40d4ab8d32ca5..e2c280bd41b39 100644 --- a/posthog/management/commands/sync_replicated_schema.py +++ b/posthog/management/commands/sync_replicated_schema.py @@ -90,7 +90,7 @@ def create_missing_tables( out_of_sync_hosts: Dict[HostName, Set[TableName]], create_table_queries: Dict[TableName, Query], ): - missing_tables = set(table for tables in out_of_sync_hosts.values() for table in tables) + missing_tables = {table for tables in out_of_sync_hosts.values() for table in tables} logger.info("Creating missing tables", missing_tables=missing_tables) for table in missing_tables: diff --git a/posthog/management/commands/test/test_migrate_kafka_data.py b/posthog/management/commands/test/test_migrate_kafka_data.py index 05bf9f0c47c3e..a53ff16cb235d 100644 --- a/posthog/management/commands/test/test_migrate_kafka_data.py +++ b/posthog/management/commands/test/test_migrate_kafka_data.py @@ -161,7 +161,7 @@ def test_cannot_send_data_back_into_same_topic_on_same_cluster(): except ValueError as e: assert str(e) == "You must specify a different topic and cluster to migrate data to" else: - assert False, "Expected ValueError to be raised" + raise AssertionError("Expected ValueError to be raised") def test_that_the_command_fails_if_the_specified_consumer_group_does_not_exist(): @@ -199,7 +199,7 @@ def test_that_the_command_fails_if_the_specified_consumer_group_does_not_exist() except ValueError as e: assert str(e) == "Consumer group nonexistent-consumer-group has no committed offsets" else: - assert False, "Expected ValueError to be raised" + raise AssertionError("Expected ValueError to be raised") def test_that_we_error_if_the_target_topic_doesnt_exist(): @@ -238,7 +238,7 @@ def test_that_we_error_if_the_target_topic_doesnt_exist(): except ValueError as e: assert str(e) == f"Topic {new_topic} does not exist" else: - assert False, "Expected ValueError to be raised" + raise AssertionError("Expected ValueError to be raised") def test_we_fail_on_send_errors_to_new_topic(): @@ -293,7 +293,7 @@ def test_we_fail_on_send_errors_to_new_topic(): except KafkaError as e: assert str(e) == "KafkaError: Failed to produce" else: - assert False, "Expected KafkaError to be raised" + raise AssertionError("Expected KafkaError to be raised") # Ensure that if we run the command again, it will not fail # and will re-consume and produce the message to the new topic. diff --git a/posthog/migrations/0046_event_names_properties_to_team.py b/posthog/migrations/0046_event_names_properties_to_team.py index 7350a5a8de701..351262f62b3e2 100644 --- a/posthog/migrations/0046_event_names_properties_to_team.py +++ b/posthog/migrations/0046_event_names_properties_to_team.py @@ -20,8 +20,8 @@ class JsonKeys(models.Func): .values_list("keys", flat=True) ) names = events.distinct("event").values_list("event", flat=True) - team.event_keys = [key for key in keys] - team.event_names = [name for name in names] + team.event_keys = list(keys) + team.event_names = list(names) team.save() diff --git a/posthog/migrations/0219_migrate_tags_v2.py b/posthog/migrations/0219_migrate_tags_v2.py index ecc4f4312a812..fef394a5cc0ea 100644 --- a/posthog/migrations/0219_migrate_tags_v2.py +++ b/posthog/migrations/0219_migrate_tags_v2.py @@ -40,7 +40,7 @@ def forwards(apps, schema_editor): ) insights = iter(insight_paginator.get_page(insight_page)) for tags, team_id, insight_id in insights: - unique_tags = set(tagify(t) for t in tags if isinstance(t, str) and t.strip() != "") + unique_tags = {tagify(t) for t in tags if isinstance(t, str) and t.strip() != ""} for tag in unique_tags: temp_tag = Tag(name=tag, team_id=team_id) createables.append((temp_tag, TaggedItem(insight_id=insight_id, tag_id=temp_tag.id))) @@ -66,7 +66,7 @@ def forwards(apps, schema_editor): ) dashboards = iter(dashboard_paginator.get_page(dashboard_page)) for tags, team_id, dashboard_id in dashboards: - unique_tags = set(tagify(t) for t in tags if isinstance(t, str) and t.strip() != "") + unique_tags = {tagify(t) for t in tags if isinstance(t, str) and t.strip() != ""} for tag in unique_tags: temp_tag = Tag(name=tag, team_id=team_id) createables.append( diff --git a/posthog/models/action/util.py b/posthog/models/action/util.py index e2940f3ecad8d..54fda6ef5b95f 100644 --- a/posthog/models/action/util.py +++ b/posthog/models/action/util.py @@ -25,7 +25,7 @@ def format_action_filter_event_only( # If selecting for "All events", disable entity pre-filtering return "1 = 1", {} entity_name = f"{prepend}_{action.pk}" - return f"event IN %({entity_name})s", {entity_name: sorted(list(events))} + return f"event IN %({entity_name})s", {entity_name: sorted(events)} def format_action_filter( diff --git a/posthog/models/async_deletion/delete.py b/posthog/models/async_deletion/delete.py index 00ab4d43ee35b..9846842b8e0d5 100644 --- a/posthog/models/async_deletion/delete.py +++ b/posthog/models/async_deletion/delete.py @@ -44,7 +44,7 @@ def mark_deletions_done(self): "Updated `delete_verified_at` for AsyncDeletion", { "count": len(to_verify), - "team_ids": list(set(row.team_id for row in to_verify)), + "team_ids": list({row.team_id for row in to_verify}), }, ) diff --git a/posthog/models/async_deletion/delete_cohorts.py b/posthog/models/async_deletion/delete_cohorts.py index 3a4737c221964..c857b18e81ee4 100644 --- a/posthog/models/async_deletion/delete_cohorts.py +++ b/posthog/models/async_deletion/delete_cohorts.py @@ -17,7 +17,7 @@ def process(self, deletions: List[AsyncDeletion]): "Starting AsyncDeletion on `cohortpeople` table in ClickHouse", { "count": len(deletions), - "team_ids": list(set(row.team_id for row in deletions)), + "team_ids": list({row.team_id for row in deletions}), }, ) @@ -50,7 +50,7 @@ def _verify_by_column(self, distinct_columns: str, async_deletions: List[AsyncDe """, args, ) - return set(tuple(row) for row in clickhouse_result) + return {tuple(row) for row in clickhouse_result} def _column_name(self, async_deletion: AsyncDeletion): assert async_deletion.deletion_type in ( diff --git a/posthog/models/async_deletion/delete_events.py b/posthog/models/async_deletion/delete_events.py index 49da11d47b884..c4cbfad639a25 100644 --- a/posthog/models/async_deletion/delete_events.py +++ b/posthog/models/async_deletion/delete_events.py @@ -29,7 +29,7 @@ def process(self, deletions: List[AsyncDeletion]): "Starting AsyncDeletion on `events` table in ClickHouse", { "count": len(deletions), - "team_ids": list(set(row.team_id for row in deletions)), + "team_ids": list({row.team_id for row in deletions}), }, ) @@ -53,7 +53,7 @@ def process(self, deletions: List[AsyncDeletion]): "Starting AsyncDeletion for teams on other tables", { "count": len(team_deletions), - "team_ids": list(set(row.team_id for row in deletions)), + "team_ids": list({row.team_id for row in deletions}), }, ) conditions, args = self._conditions(team_deletions) @@ -73,7 +73,7 @@ def _verify_by_group(self, deletion_type: int, async_deletions: List[AsyncDeleti return [row for row in async_deletions if (row.team_id,) not in team_ids_with_data] elif deletion_type in (DeletionType.Person, DeletionType.Group): columns = f"team_id, {self._column_name(async_deletions[0])}" - with_data = set((team_id, str(key)) for team_id, key in self._verify_by_column(columns, async_deletions)) + with_data = {(team_id, str(key)) for team_id, key in self._verify_by_column(columns, async_deletions)} return [row for row in async_deletions if (row.team_id, row.key) not in with_data] else: return [] @@ -88,7 +88,7 @@ def _verify_by_column(self, distinct_columns: str, async_deletions: List[AsyncDe """, args, ) - return set(tuple(row) for row in clickhouse_result) + return {tuple(row) for row in clickhouse_result} def _column_name(self, async_deletion: AsyncDeletion): assert async_deletion.deletion_type in (DeletionType.Person, DeletionType.Group) diff --git a/posthog/models/channel_type/sql.py b/posthog/models/channel_type/sql.py index 35774a19aa586..15470601c2dfb 100644 --- a/posthog/models/channel_type/sql.py +++ b/posthog/models/channel_type/sql.py @@ -54,7 +54,7 @@ def format_value(value): INSERT INTO channel_definition (domain, kind, domain_type, type_if_paid, type_if_organic) VALUES { ''', -'''.join(map(lambda x: f'({" ,".join(map(format_value, x))})', CHANNEL_DEFINITIONS))}, +'''.join((f'({" ,".join(map(format_value, x))})' for x in CHANNEL_DEFINITIONS))}, ; """ diff --git a/posthog/models/cohort/cohort.py b/posthog/models/cohort/cohort.py index 59d144fdd549f..cb81db1e606a7 100644 --- a/posthog/models/cohort/cohort.py +++ b/posthog/models/cohort/cohort.py @@ -273,7 +273,7 @@ def insert_users_by_list(self, items: List[str]) -> None: .exclude(cohort__id=self.id) ) insert_static_cohort( - [p for p in persons_query.values_list("uuid", flat=True)], + list(persons_query.values_list("uuid", flat=True)), self.pk, self.team, ) @@ -315,7 +315,7 @@ def insert_users_list_by_uuid(self, items: List[str], insert_in_clickhouse: bool ) if insert_in_clickhouse: insert_static_cohort( - [p for p in persons_query.values_list("uuid", flat=True)], + list(persons_query.values_list("uuid", flat=True)), self.pk, self.team, ) diff --git a/posthog/models/event/util.py b/posthog/models/event/util.py index 9fe98305d693a..184c6831f1977 100644 --- a/posthog/models/event/util.py +++ b/posthog/models/event/util.py @@ -31,7 +31,7 @@ def create_event( team: Team, distinct_id: str, timestamp: Optional[Union[timezone.datetime, str]] = None, - properties: Optional[Dict] = {}, + properties: Optional[Dict] = None, elements: Optional[List[Element]] = None, person_id: Optional[uuid.UUID] = None, person_properties: Optional[Dict] = None, @@ -47,6 +47,8 @@ def create_event( group3_created_at: Optional[Union[timezone.datetime, str]] = None, group4_created_at: Optional[Union[timezone.datetime, str]] = None, ) -> str: + if properties is None: + properties = {} if not timestamp: timestamp = timezone.now() assert timestamp is not None @@ -277,9 +279,11 @@ class Meta: ] -def parse_properties(properties: str, allow_list: Set[str] = set()) -> Dict: +def parse_properties(properties: str, allow_list: Set[str] = None) -> Dict: # parse_constants gets called for any NaN, Infinity etc values # we just want those to be returned as None + if allow_list is None: + allow_list = set() props = json.loads(properties or "{}", parse_constant=lambda x: None) return { key: value.strip('"') if isinstance(value, str) else value diff --git a/posthog/models/feature_flag/flag_matching.py b/posthog/models/feature_flag/flag_matching.py index c3ae073b7c9ad..7ccc695822f38 100644 --- a/posthog/models/feature_flag/flag_matching.py +++ b/posthog/models/feature_flag/flag_matching.py @@ -132,14 +132,22 @@ def __init__( self, feature_flags: List[FeatureFlag], distinct_id: str, - groups: Dict[GroupTypeName, str] = {}, + groups: Dict[GroupTypeName, str] = None, cache: Optional[FlagsMatcherCache] = None, - hash_key_overrides: Dict[str, str] = {}, - property_value_overrides: Dict[str, Union[str, int]] = {}, - group_property_value_overrides: Dict[str, Dict[str, Union[str, int]]] = {}, + hash_key_overrides: Dict[str, str] = None, + property_value_overrides: Dict[str, Union[str, int]] = None, + group_property_value_overrides: Dict[str, Dict[str, Union[str, int]]] = None, skip_database_flags: bool = False, cohorts_cache: Optional[Dict[int, CohortOrEmpty]] = None, ): + if group_property_value_overrides is None: + group_property_value_overrides = {} + if property_value_overrides is None: + property_value_overrides = {} + if hash_key_overrides is None: + hash_key_overrides = {} + if groups is None: + groups = {} self.feature_flags = feature_flags self.distinct_id = distinct_id self.groups = groups @@ -629,7 +637,7 @@ def get_feature_flag_hash_key_overrides( .filter(distinct_id__in=distinct_ids, team_id=team_id) .values_list("person_id", "distinct_id") ) - person_id_to_distinct_id = {person_id: distinct_id for person_id, distinct_id in person_and_distinct_ids} + person_id_to_distinct_id = dict(person_and_distinct_ids) else: person_id_to_distinct_id = person_id_to_distinct_id_mapping @@ -653,11 +661,17 @@ def _get_all_feature_flags( team_id: int, distinct_id: str, person_overrides: Optional[Dict[str, str]] = None, - groups: Dict[GroupTypeName, str] = {}, - property_value_overrides: Dict[str, Union[str, int]] = {}, - group_property_value_overrides: Dict[str, Dict[str, Union[str, int]]] = {}, + groups: Dict[GroupTypeName, str] = None, + property_value_overrides: Dict[str, Union[str, int]] = None, + group_property_value_overrides: Dict[str, Dict[str, Union[str, int]]] = None, skip_database_flags: bool = False, ) -> Tuple[Dict[str, Union[str, bool]], Dict[str, dict], Dict[str, object], bool]: + if group_property_value_overrides is None: + group_property_value_overrides = {} + if property_value_overrides is None: + property_value_overrides = {} + if groups is None: + groups = {} cache = FlagsMatcherCache(team_id) if feature_flags: @@ -679,11 +693,17 @@ def _get_all_feature_flags( def get_all_feature_flags( team_id: int, distinct_id: str, - groups: Dict[GroupTypeName, str] = {}, + groups: Dict[GroupTypeName, str] = None, hash_key_override: Optional[str] = None, - property_value_overrides: Dict[str, Union[str, int]] = {}, - group_property_value_overrides: Dict[str, Dict[str, Union[str, int]]] = {}, + property_value_overrides: Dict[str, Union[str, int]] = None, + group_property_value_overrides: Dict[str, Dict[str, Union[str, int]]] = None, ) -> Tuple[Dict[str, Union[str, bool]], Dict[str, dict], Dict[str, object], bool]: + if group_property_value_overrides is None: + group_property_value_overrides = {} + if property_value_overrides is None: + property_value_overrides = {} + if groups is None: + groups = {} property_value_overrides, group_property_value_overrides = add_local_person_and_group_properties( distinct_id, groups, property_value_overrides, group_property_value_overrides ) diff --git a/posthog/models/filters/mixins/common.py b/posthog/models/filters/mixins/common.py index f0717c3d47f0b..347a343de3ffc 100644 --- a/posthog/models/filters/mixins/common.py +++ b/posthog/models/filters/mixins/common.py @@ -521,7 +521,7 @@ def entities_to_dict(self): @include_query_tags def entities_query_tags(self): - return {"entity_math": list(set(entity.math for entity in self.entities if entity.math))} + return {"entity_math": list({entity.math for entity in self.entities if entity.math})} # These arguments are used to specify the target entity for insight actor retrieval on trend graphs diff --git a/posthog/models/filters/mixins/property.py b/posthog/models/filters/mixins/property.py index 7ca409d4897d1..ff4cb56fee91a 100644 --- a/posthog/models/filters/mixins/property.py +++ b/posthog/models/filters/mixins/property.py @@ -134,9 +134,9 @@ def properties_to_dict(self): @include_query_tags def properties_query_tags(self): - filter_by_type = set(prop.type for prop in self.property_groups.flat) + filter_by_type = {prop.type for prop in self.property_groups.flat} for entity in getattr(self, "entities", []): - filter_by_type |= set(prop.type for prop in entity.property_groups.flat) + filter_by_type |= {prop.type for prop in entity.property_groups.flat} return {"filter_by_type": list(filter_by_type)} diff --git a/posthog/models/filters/retention_filter.py b/posthog/models/filters/retention_filter.py index 9cc3e8d0c7a08..fcf5559fb2158 100644 --- a/posthog/models/filters/retention_filter.py +++ b/posthog/models/filters/retention_filter.py @@ -48,7 +48,9 @@ class RetentionFilter( SampleMixin, BaseFilter, ): - def __init__(self, data: Dict[str, Any] = {}, request: Optional[Request] = None, **kwargs) -> None: + def __init__(self, data: Dict[str, Any] = None, request: Optional[Request] = None, **kwargs) -> None: + if data is None: + data = {} if data: data["insight"] = INSIGHT_RETENTION else: diff --git a/posthog/models/filters/test/test_filter.py b/posthog/models/filters/test/test_filter.py index a584bbd415916..5a7ae26637494 100644 --- a/posthog/models/filters/test/test_filter.py +++ b/posthog/models/filters/test/test_filter.py @@ -993,8 +993,10 @@ def filter_persons_with_annotation(filter: Filter, team: Team): def filter_persons_with_property_group( - filter: Filter, team: Team, property_overrides: Dict[str, Any] = {} + filter: Filter, team: Team, property_overrides: Dict[str, Any] = None ) -> List[str]: + if property_overrides is None: + property_overrides = {} flush_persons_and_events() persons = Person.objects.filter(property_group_to_Q(team.pk, filter.property_groups, property_overrides)) persons = persons.filter(team_id=team.pk) diff --git a/posthog/models/filters/utils.py b/posthog/models/filters/utils.py index 0b31b209afa69..fd9162d6dab60 100644 --- a/posthog/models/filters/utils.py +++ b/posthog/models/filters/utils.py @@ -21,12 +21,14 @@ def earliest_timestamp_func(team_id: int): return get_earliest_timestamp(team_id) -def get_filter(team, data: dict = {}, request: Optional[Request] = None): +def get_filter(team, data: dict = None, request: Optional[Request] = None): from .filter import Filter from .path_filter import PathFilter from .retention_filter import RetentionFilter from .stickiness_filter import StickinessFilter + if data is None: + data = {} insight = data.get("insight") if not insight and request: insight = request.GET.get("insight") or request.data.get("insight") diff --git a/posthog/models/person/util.py b/posthog/models/person/util.py index 7e8afc3db5e78..f6bcc60ebc333 100644 --- a/posthog/models/person/util.py +++ b/posthog/models/person/util.py @@ -127,13 +127,15 @@ def create_person( team_id: int, version: int, uuid: Optional[str] = None, - properties: Optional[Dict] = {}, + properties: Optional[Dict] = None, sync: bool = False, is_identified: bool = False, is_deleted: bool = False, timestamp: Optional[Union[datetime.datetime, str]] = None, created_at: Optional[datetime.datetime] = None, ) -> str: + if properties is None: + properties = {} if uuid: uuid = str(uuid) else: diff --git a/posthog/models/plugin.py b/posthog/models/plugin.py index bdd1a5f8f496e..da559a377895e 100644 --- a/posthog/models/plugin.py +++ b/posthog/models/plugin.py @@ -421,8 +421,10 @@ def fetch_plugin_log_entries( before: Optional[timezone.datetime] = None, search: Optional[str] = None, limit: Optional[int] = None, - type_filter: List[PluginLogEntryType] = [], + type_filter: List[PluginLogEntryType] = None, ) -> List[PluginLogEntry]: + if type_filter is None: + type_filter = [] clickhouse_where_parts: List[str] = [] clickhouse_kwargs: Dict[str, Any] = {} if team_id is not None: diff --git a/posthog/models/test/test_event_model.py b/posthog/models/test/test_event_model.py index cbe6a2bcad70c..f0e7b62c3acff 100644 --- a/posthog/models/test/test_event_model.py +++ b/posthog/models/test/test_event_model.py @@ -128,7 +128,7 @@ def _setup_action_selector_events(self): def assertActionEventsMatch(self, action, expected_events): events = _get_events_for_action(action) - self.assertCountEqual([e.uuid for e in events], [event_uuid for event_uuid in expected_events]) + self.assertCountEqual([e.uuid for e in events], list(expected_events)) def test_with_normal_filters(self): # this test also specifically tests the back to back receipt of diff --git a/posthog/models/test/test_person_override_model.py b/posthog/models/test/test_person_override_model.py index 13f3b0a8511ab..7a1929d6cd9c7 100644 --- a/posthog/models/test/test_person_override_model.py +++ b/posthog/models/test/test_person_override_model.py @@ -394,7 +394,7 @@ def test_person_override_allows_duplicate_override_person_id(team, oldest_event) created.append(person_override) assert all(p.override_person_id == override_mapping for p in created) - assert len(set(p.old_person_id.uuid for p in created)) == n_person_overrides + assert len({p.old_person_id.uuid for p in created}) == n_person_overrides @contextlib.contextmanager diff --git a/posthog/models/test/test_subscription_model.py b/posthog/models/test/test_subscription_model.py index 8552d8bca795a..0369c7d3c590e 100644 --- a/posthog/models/test/test_subscription_model.py +++ b/posthog/models/test/test_subscription_model.py @@ -25,16 +25,16 @@ class TestSubscription(BaseTest): def _create_insight_subscription(self, **kwargs): insight = Insight.objects.create(team=self.team) - params = dict( - team=self.team, - title="My Subscription", - insight=insight, - target_type="email", - target_value="tests@posthog.com", - frequency="weekly", - interval=2, - start_date=datetime(2022, 1, 1, 0, 0, 0, 0).replace(tzinfo=ZoneInfo("UTC")), - ) + params = { + "team": self.team, + "title": "My Subscription", + "insight": insight, + "target_type": "email", + "target_value": "tests@posthog.com", + "frequency": "weekly", + "interval": 2, + "start_date": datetime(2022, 1, 1, 0, 0, 0, 0).replace(tzinfo=ZoneInfo("UTC")), + } params.update(**kwargs) return Subscription.objects.create(**params) diff --git a/posthog/models/utils.py b/posthog/models/utils.py index b00a87eb881c5..427610c81a598 100644 --- a/posthog/models/utils.py +++ b/posthog/models/utils.py @@ -206,7 +206,7 @@ def create_with_slug(create_func: Callable[..., T], default_slug: str = "", *arg def get_deferred_field_set_for_model( model: Type[models.Model], - fields_not_deferred: Set[str] = set(), + fields_not_deferred: Set[str] = None, field_prefix: str = "", ) -> Set[str]: """Return a set of field names to be deferred for a given model. Used with `.defer()` after `select_related` @@ -225,6 +225,8 @@ def get_deferred_field_set_for_model( fields_not_deferred: the models fields to exclude from the deferred field set field_prefix: a prefix to add to the field names e.g. ("team__organization__") to work in the query set """ + if fields_not_deferred is None: + fields_not_deferred = set() return {f"{field_prefix}{x.name}" for x in model._meta.fields if x.name not in fields_not_deferred} diff --git a/posthog/queries/actor_base_query.py b/posthog/queries/actor_base_query.py index 6757a14f1cd97..66c476cd814cd 100644 --- a/posthog/queries/actor_base_query.py +++ b/posthog/queries/actor_base_query.py @@ -148,7 +148,7 @@ def query_for_session_ids_with_recordings( params = { "team_id": self._team.pk, - "session_ids": sorted(list(session_ids)), # Sort for stable queries + "session_ids": sorted(session_ids), # Sort for stable queries # widen the date range a little # we don't want to exclude sessions that start or end within a # reasonable time of the query date range diff --git a/posthog/queries/base.py b/posthog/queries/base.py index 78ea402e4ee87..ac4628601f668 100644 --- a/posthog/queries/base.py +++ b/posthog/queries/base.py @@ -274,10 +274,12 @@ def lookup_q(key: str, value: Any) -> Q: def property_to_Q( team_id: int, property: Property, - override_property_values: Dict[str, Any] = {}, + override_property_values: Dict[str, Any] = None, cohorts_cache: Optional[Dict[int, CohortOrEmpty]] = None, using_database: str = "default", ) -> Q: + if override_property_values is None: + override_property_values = {} if property.type not in ["person", "group", "cohort", "event"]: # We need to support event type for backwards compatibility, even though it's treated as a person property type raise ValueError(f"property_to_Q: type is not supported: {repr(property.type)}") @@ -378,10 +380,12 @@ def property_to_Q( def property_group_to_Q( team_id: int, property_group: PropertyGroup, - override_property_values: Dict[str, Any] = {}, + override_property_values: Dict[str, Any] = None, cohorts_cache: Optional[Dict[int, CohortOrEmpty]] = None, using_database: str = "default", ) -> Q: + if override_property_values is None: + override_property_values = {} filters = Q() if not property_group or len(property_group.values) == 0: @@ -421,7 +425,7 @@ def property_group_to_Q( def properties_to_Q( team_id: int, properties: List[Property], - override_property_values: Dict[str, Any] = {}, + override_property_values: Dict[str, Any] = None, cohorts_cache: Optional[Dict[int, CohortOrEmpty]] = None, using_database: str = "default", ) -> Q: @@ -429,6 +433,8 @@ def properties_to_Q( Converts a filter to Q, for use in Django ORM .filter() If you're filtering a Person/Group QuerySet, use is_direct_query to avoid doing an unnecessary nested loop """ + if override_property_values is None: + override_property_values = {} filters = Q() if len(properties) == 0: diff --git a/posthog/queries/breakdown_props.py b/posthog/queries/breakdown_props.py index 64a550edf543d..8e32b431daf7c 100644 --- a/posthog/queries/breakdown_props.py +++ b/posthog/queries/breakdown_props.py @@ -46,7 +46,7 @@ def get_breakdown_prop_values( entity: Entity, aggregate_operation: str, team: Team, - extra_params={}, + extra_params=None, column_optimizer: Optional[ColumnOptimizer] = None, person_properties_mode: PersonPropertiesMode = PersonPropertiesMode.USING_PERSON_PROPERTIES_COLUMN, use_all_funnel_entities: bool = False, @@ -58,6 +58,8 @@ def get_breakdown_prop_values( When dealing with a histogram though, buckets are returned instead of values. """ + if extra_params is None: + extra_params = {} column_optimizer = column_optimizer or ColumnOptimizer(filter, team.id) date_params = {} diff --git a/posthog/queries/column_optimizer/foss_column_optimizer.py b/posthog/queries/column_optimizer/foss_column_optimizer.py index 19487a7cb5de4..98dfb1b54c418 100644 --- a/posthog/queries/column_optimizer/foss_column_optimizer.py +++ b/posthog/queries/column_optimizer/foss_column_optimizer.py @@ -74,10 +74,10 @@ def columns_to_query( "Transforms a list of property names to what columns are needed for that query" materialized_columns = get_materialized_columns(table) - return set( + return { materialized_columns.get((property_name, table_column), table_column) for property_name, _, _ in used_properties - ) + } @cached_property def is_using_person_properties(self) -> bool: diff --git a/posthog/queries/event_query/event_query.py b/posthog/queries/event_query/event_query.py index 862e6d8f03495..b75bac528592b 100644 --- a/posthog/queries/event_query/event_query.py +++ b/posthog/queries/event_query/event_query.py @@ -60,13 +60,19 @@ def __init__( should_join_persons=False, should_join_sessions=False, # Extra events/person table columns to fetch since parent query needs them - extra_fields: List[ColumnName] = [], - extra_event_properties: List[PropertyName] = [], - extra_person_fields: List[ColumnName] = [], + extra_fields: List[ColumnName] = None, + extra_event_properties: List[PropertyName] = None, + extra_person_fields: List[ColumnName] = None, override_aggregate_users_by_distinct_id: Optional[bool] = None, person_on_events_mode: PersonOnEventsMode = PersonOnEventsMode.DISABLED, **kwargs, ) -> None: + if extra_person_fields is None: + extra_person_fields = [] + if extra_event_properties is None: + extra_event_properties = [] + if extra_fields is None: + extra_fields = [] self._filter = filter self._team_id = team.pk self._team = team diff --git a/posthog/queries/foss_cohort_query.py b/posthog/queries/foss_cohort_query.py index e6005abab632a..b611767ce2eb6 100644 --- a/posthog/queries/foss_cohort_query.py +++ b/posthog/queries/foss_cohort_query.py @@ -136,12 +136,18 @@ def __init__( should_join_distinct_ids=False, should_join_persons=False, # Extra events/person table columns to fetch since parent query needs them - extra_fields: List[ColumnName] = [], - extra_event_properties: List[PropertyName] = [], - extra_person_fields: List[ColumnName] = [], + extra_fields: List[ColumnName] = None, + extra_event_properties: List[PropertyName] = None, + extra_person_fields: List[ColumnName] = None, override_aggregate_users_by_distinct_id: Optional[bool] = None, **kwargs, ) -> None: + if extra_person_fields is None: + extra_person_fields = [] + if extra_event_properties is None: + extra_event_properties = [] + if extra_fields is None: + extra_fields = [] self._fields = [] self._events = [] self._earliest_time_for_event_query = None diff --git a/posthog/queries/funnels/base.py b/posthog/queries/funnels/base.py index e52880f6a091d..244ede082b7ac 100644 --- a/posthog/queries/funnels/base.py +++ b/posthog/queries/funnels/base.py @@ -600,7 +600,7 @@ def _get_funnel_person_step_condition(self): conditions.append("steps IN %(custom_step_num)s") elif step_num is not None: if step_num >= 0: - self.params.update({"step_num": [i for i in range(step_num, max_steps + 1)]}) + self.params.update({"step_num": list(range(step_num, max_steps + 1))}) conditions.append("steps IN %(step_num)s") else: self.params.update({"step_num": abs(step_num) - 1}) diff --git a/posthog/queries/funnels/funnel_event_query.py b/posthog/queries/funnels/funnel_event_query.py index 9d750eb604652..01c2f6af00497 100644 --- a/posthog/queries/funnels/funnel_event_query.py +++ b/posthog/queries/funnels/funnel_event_query.py @@ -160,4 +160,4 @@ def _get_entity_query(self, entities=None, entity_name="events") -> Tuple[str, D if None in events: return "AND 1 = 1", {} - return f"AND event IN %({entity_name})s", {entity_name: sorted(list(events))} + return f"AND event IN %({entity_name})s", {entity_name: sorted(events)} diff --git a/posthog/queries/funnels/test/breakdown_cases.py b/posthog/queries/funnels/test/breakdown_cases.py index 273ce3b201601..b38384c745e90 100644 --- a/posthog/queries/funnels/test/breakdown_cases.py +++ b/posthog/queries/funnels/test/breakdown_cases.py @@ -2647,7 +2647,7 @@ def test_funnel_breakdown_correct_breakdown_props_are_chosen_for_step(self): def sort_breakdown_funnel_results(results: List[Dict[int, Any]]): - return list(sorted(results, key=lambda r: r[0]["breakdown_value"])) + return sorted(results, key=lambda r: r[0]["breakdown_value"]) def assert_funnel_results_equal(left: List[Dict[str, Any]], right: List[Dict[str, Any]]): diff --git a/posthog/queries/funnels/test/test_breakdowns_by_current_url.py b/posthog/queries/funnels/test/test_breakdowns_by_current_url.py index bb6673387b64d..ee71eb59753d3 100644 --- a/posthog/queries/funnels/test/test_breakdowns_by_current_url.py +++ b/posthog/queries/funnels/test/test_breakdowns_by_current_url.py @@ -115,7 +115,11 @@ def setUp(self): journeys_for(journey, team=self.team, create_people=True) - def _run(self, extra: Dict = {}, events_extra: Dict = {}): + def _run(self, extra: Dict = None, events_extra: Dict = None): + if events_extra is None: + events_extra = {} + if extra is None: + extra = {} response = ClickhouseFunnel( Filter( data={ diff --git a/posthog/queries/funnels/test/test_funnel.py b/posthog/queries/funnels/test/test_funnel.py index 334f0dc9c41c0..d519c5b7b50d9 100644 --- a/posthog/queries/funnels/test/test_funnel.py +++ b/posthog/queries/funnels/test/test_funnel.py @@ -3024,7 +3024,7 @@ def test_breakdown_values_is_set_on_the_query_with_fewer_than_two_entities(self) try: ClickhouseFunnel(Filter(data=filter_with_breakdown), self.team).run() except KeyError as ke: - assert False, f"Should not have raised a key error: {ke}" + raise AssertionError(f"Should not have raised a key error: {ke}") @snapshot_clickhouse_queries def test_funnel_with_cohorts_step_filter(self): diff --git a/posthog/queries/properties_timeline/properties_timeline.py b/posthog/queries/properties_timeline/properties_timeline.py index fbf7cff240243..34c392353098a 100644 --- a/posthog/queries/properties_timeline/properties_timeline.py +++ b/posthog/queries/properties_timeline/properties_timeline.py @@ -146,7 +146,7 @@ def run( ) for timestamp, properties, relevant_event_count in raw_query_result ], - crucial_property_keys=list(sorted(crucial_property_keys)), + crucial_property_keys=sorted(crucial_property_keys), effective_date_from=event_query.effective_date_from.isoformat(), effective_date_to=event_query.effective_date_to.isoformat(), ) diff --git a/posthog/queries/retention/retention.py b/posthog/queries/retention/retention.py index 24cbe95376e93..5536a02940b9e 100644 --- a/posthog/queries/retention/retention.py +++ b/posthog/queries/retention/retention.py @@ -94,7 +94,7 @@ def process_breakdown_table_result(self, resultset: Dict[CohortKey, Dict[str, An f"{urlencode(RetentionFilter({**filter._data, 'display': 'ActionsTable', 'breakdown_values': breakdown_values}).to_params())}" ), } - for breakdown_values in set(cohort_key.breakdown_values for cohort_key in resultset.keys()) + for breakdown_values in {cohort_key.breakdown_values for cohort_key in resultset.keys()} ] return result diff --git a/posthog/queries/stickiness/stickiness.py b/posthog/queries/stickiness/stickiness.py index 08bea51c8b042..50c2ff81ad987 100644 --- a/posthog/queries/stickiness/stickiness.py +++ b/posthog/queries/stickiness/stickiness.py @@ -85,7 +85,7 @@ def process_result(self, counts: List, filter: StickinessFilter, entity: Entity) return { "labels": labels, - "days": [day for day in range(1, filter.total_intervals)], + "days": list(range(1, filter.total_intervals)), "data": data, "count": sum(data), "filter": filter_params, diff --git a/posthog/queries/test/test_lifecycle.py b/posthog/queries/test/test_lifecycle.py index e50d5cc4ad29a..9c1c9e0dc5532 100644 --- a/posthog/queries/test/test_lifecycle.py +++ b/posthog/queries/test/test_lifecycle.py @@ -30,7 +30,7 @@ def assertLifecycleResults(self, results, expected): sorted_results = [ {"status": r["status"], "data": r["data"]} for r in sorted(results, key=lambda r: r["status"]) ] - sorted_expected = list(sorted(expected, key=lambda r: r["status"])) + sorted_expected = sorted(expected, key=lambda r: r["status"]) self.assertListEqual(sorted_results, sorted_expected) diff --git a/posthog/queries/trends/test/test_breakdowns.py b/posthog/queries/trends/test/test_breakdowns.py index 48ed9033c0458..78da6f94dcfa5 100644 --- a/posthog/queries/trends/test/test_breakdowns.py +++ b/posthog/queries/trends/test/test_breakdowns.py @@ -104,7 +104,11 @@ def setUp(self): journeys_for(journey, team=self.team, create_people=True) - def _run(self, extra: Dict = {}, events_extra: Dict = {}): + def _run(self, extra: Dict = None, events_extra: Dict = None): + if events_extra is None: + events_extra = {} + if extra is None: + extra = {} response = Trends().run( Filter( data={ diff --git a/posthog/queries/trends/test/test_breakdowns_by_current_url.py b/posthog/queries/trends/test/test_breakdowns_by_current_url.py index bc7a81595843b..49d94fec68b12 100644 --- a/posthog/queries/trends/test/test_breakdowns_by_current_url.py +++ b/posthog/queries/trends/test/test_breakdowns_by_current_url.py @@ -99,7 +99,11 @@ def setUp(self): journeys_for(journey, team=self.team, create_people=True) - def _run(self, extra: Dict = {}, events_extra: Dict = {}): + def _run(self, extra: Dict = None, events_extra: Dict = None): + if events_extra is None: + events_extra = {} + if extra is None: + extra = {} response = Trends().run( Filter( data={ diff --git a/posthog/queries/trends/test/test_formula.py b/posthog/queries/trends/test/test_formula.py index adbf54fa05f79..83af065d5dc03 100644 --- a/posthog/queries/trends/test/test_formula.py +++ b/posthog/queries/trends/test/test_formula.py @@ -129,7 +129,9 @@ def setUp(self): }, ) - def _run(self, extra: Dict = {}, run_at: Optional[str] = None): + def _run(self, extra: Dict = None, run_at: Optional[str] = None): + if extra is None: + extra = {} with freeze_time(run_at or "2020-01-04T13:01:01Z"): action_response = Trends().run( Filter( diff --git a/posthog/queries/trends/test/test_paging_breakdowns.py b/posthog/queries/trends/test/test_paging_breakdowns.py index a72e0aa88c889..a1d4ec97243b4 100644 --- a/posthog/queries/trends/test/test_paging_breakdowns.py +++ b/posthog/queries/trends/test/test_paging_breakdowns.py @@ -37,7 +37,9 @@ def setUp(self): create_people=True, ) - def _run(self, extra: Dict = {}, run_at: Optional[str] = None): + def _run(self, extra: Dict = None, run_at: Optional[str] = None): + if extra is None: + extra = {} with freeze_time(run_at or "2020-01-04T13:01:01Z"): action_response = Trends().run( Filter( @@ -63,14 +65,14 @@ def test_with_breakdown_loads_two_unqiue_pages_of_values(self): assert len(response) == 26 page_labels = [r["label"] for r in response if r["label"] != "Other"] assert len(page_labels) == 25 - assert sorted(page_labels), sorted(list(set(page_labels))) # all values are unique + assert sorted(page_labels), sorted(set(page_labels)) # all values are unique second_page_response = self._run({"breakdown": "wildcard_route", "breakdown_type": "event", "offset": 25}) second_page_labels = [r["label"] for r in second_page_response if r["label"] != "Other"] assert len(page_labels) == len(second_page_labels) # should be two pages of different results - assert sorted(second_page_labels) == sorted(list(set(second_page_labels))) # all values are unique + assert sorted(second_page_labels) == sorted(set(second_page_labels)) # all values are unique # no values from page one should be in page two assert [value for value in second_page_labels if value in page_labels] == [] diff --git a/posthog/queries/trends/util.py b/posthog/queries/trends/util.py index 382201a9e0203..04302f982ec0f 100644 --- a/posthog/queries/trends/util.py +++ b/posthog/queries/trends/util.py @@ -102,9 +102,11 @@ def process_math( def parse_response( stats: Dict, filter: Filter, - additional_values: Dict = {}, + additional_values: Dict = None, entity: Optional[Entity] = None, ) -> Dict[str, Any]: + if additional_values is None: + additional_values = {} counts = stats[1] labels = [item.strftime("%-d-%b-%Y{}".format(" %H:%M" if filter.interval == "hour" else "")) for item in stats[0]] days = [item.strftime("%Y-%m-%d{}".format(" %H:%M:%S" if filter.interval == "hour" else "")) for item in stats[0]] diff --git a/posthog/session_recordings/queries/test/test_session_recording_properties.py b/posthog/session_recordings/queries/test/test_session_recording_properties.py index aa152b0b2fa16..7972eb742abb0 100644 --- a/posthog/session_recordings/queries/test/test_session_recording_properties.py +++ b/posthog/session_recordings/queries/test/test_session_recording_properties.py @@ -25,8 +25,10 @@ def create_event( timestamp, team=None, event_name="$pageview", - properties={"$os": "Windows 95", "$current_url": "aloha.com/2"}, + properties=None, ): + if properties is None: + properties = {"$os": "Windows 95", "$current_url": "aloha.com/2"} if team is None: team = self.team _create_event( diff --git a/posthog/session_recordings/test/test_session_recording_helpers.py b/posthog/session_recordings/test/test_session_recording_helpers.py index 8597b70084c42..1fd6bb3191948 100644 --- a/posthog/session_recordings/test/test_session_recording_helpers.py +++ b/posthog/session_recordings/test/test_session_recording_helpers.py @@ -23,7 +23,7 @@ def create_activity_data(timestamp: datetime, is_active: bool): return SessionRecordingEventSummary( timestamp=round(timestamp.timestamp() * 1000), type=3, - data=dict(source=1 if is_active else -1), + data={"source": 1 if is_active else -1}, ) diff --git a/posthog/tasks/exports/image_exporter.py b/posthog/tasks/exports/image_exporter.py index 1961d9a456053..e438e86c5caeb 100644 --- a/posthog/tasks/exports/image_exporter.py +++ b/posthog/tasks/exports/image_exporter.py @@ -158,7 +158,7 @@ def _screenshot_asset( if driver: # If we encounter issues getting extra info we should silently fail rather than creating a new exception try: - all_logs = [x for x in driver.get_log("browser")] + all_logs = list(driver.get_log("browser")) scope.add_attachment(json.dumps(all_logs).encode("utf-8"), "logs.txt") except Exception: pass diff --git a/posthog/tasks/exports/test/test_csv_exporter.py b/posthog/tasks/exports/test/test_csv_exporter.py index 37c6f1e139d7d..1bb511a43173a 100644 --- a/posthog/tasks/exports/test/test_csv_exporter.py +++ b/posthog/tasks/exports/test/test_csv_exporter.py @@ -273,7 +273,7 @@ def test_csv_exporter_excel(self, mocked_object_storage_write: Any, mocked_uuidt wb = load_workbook(filename=BytesIO(exported_asset.content)) ws = wb.active - data = [row for row in ws.iter_rows(values_only=True)] + data = list(ws.iter_rows(values_only=True)) assert data == [ ("distinct_id", "properties.$browser", "event", "tomato"), ("2", "Safari", "event_name", None), diff --git a/posthog/tasks/usage_report.py b/posthog/tasks/usage_report.py index c2daef6a4ec73..da4bf2b1d245e 100644 --- a/posthog/tasks/usage_report.py +++ b/posthog/tasks/usage_report.py @@ -64,12 +64,12 @@ QUERY_RETRY_DELAY = 1 QUERY_RETRY_BACKOFF = 2 -USAGE_REPORT_TASK_KWARGS = dict( - queue=CeleryQueue.USAGE_REPORTS.value, - ignore_result=True, - autoretry_for=(Exception,), - retry_backoff=True, -) +USAGE_REPORT_TASK_KWARGS = { + "queue": CeleryQueue.USAGE_REPORTS.value, + "ignore_result": True, + "autoretry_for": (Exception,), + "retry_backoff": True, +} @dataclasses.dataclass @@ -677,153 +677,155 @@ def _get_all_usage_data(period_start: datetime, period_end: datetime) -> Dict[st Gets all usage data for the specified period. Clickhouse is good at counting things so we count across all teams rather than doing it one by one """ - return dict( - teams_with_event_count_lifetime=get_teams_with_event_count_lifetime(), - teams_with_event_count_in_period=get_teams_with_billable_event_count_in_period( + return { + "teams_with_event_count_lifetime": get_teams_with_event_count_lifetime(), + "teams_with_event_count_in_period": get_teams_with_billable_event_count_in_period( period_start, period_end, count_distinct=True ), - teams_with_event_count_in_month=get_teams_with_billable_event_count_in_period( + "teams_with_event_count_in_month": get_teams_with_billable_event_count_in_period( period_start.replace(day=1), period_end ), - teams_with_event_count_with_groups_in_period=get_teams_with_event_count_with_groups_in_period( + "teams_with_event_count_with_groups_in_period": get_teams_with_event_count_with_groups_in_period( period_start, period_end ), # teams_with_event_count_by_lib=get_teams_with_event_count_by_lib(period_start, period_end), # teams_with_event_count_by_name=get_teams_with_event_count_by_name(period_start, period_end), - teams_with_recording_count_in_period=get_teams_with_recording_count_in_period(period_start, period_end), - teams_with_recording_count_total=get_teams_with_recording_count_total(), - teams_with_decide_requests_count_in_period=get_teams_with_feature_flag_requests_count_in_period( + "teams_with_recording_count_in_period": get_teams_with_recording_count_in_period(period_start, period_end), + "teams_with_recording_count_total": get_teams_with_recording_count_total(), + "teams_with_decide_requests_count_in_period": get_teams_with_feature_flag_requests_count_in_period( period_start, period_end, FlagRequestType.DECIDE ), - teams_with_decide_requests_count_in_month=get_teams_with_feature_flag_requests_count_in_period( + "teams_with_decide_requests_count_in_month": get_teams_with_feature_flag_requests_count_in_period( period_start.replace(day=1), period_end, FlagRequestType.DECIDE ), - teams_with_local_evaluation_requests_count_in_period=get_teams_with_feature_flag_requests_count_in_period( + "teams_with_local_evaluation_requests_count_in_period": get_teams_with_feature_flag_requests_count_in_period( period_start, period_end, FlagRequestType.LOCAL_EVALUATION ), - teams_with_local_evaluation_requests_count_in_month=get_teams_with_feature_flag_requests_count_in_period( + "teams_with_local_evaluation_requests_count_in_month": get_teams_with_feature_flag_requests_count_in_period( period_start.replace(day=1), period_end, FlagRequestType.LOCAL_EVALUATION ), - teams_with_group_types_total=list( + "teams_with_group_types_total": list( GroupTypeMapping.objects.values("team_id").annotate(total=Count("id")).order_by("team_id") ), - teams_with_dashboard_count=list( + "teams_with_dashboard_count": list( Dashboard.objects.values("team_id").annotate(total=Count("id")).order_by("team_id") ), - teams_with_dashboard_template_count=list( + "teams_with_dashboard_template_count": list( Dashboard.objects.filter(creation_mode="template") .values("team_id") .annotate(total=Count("id")) .order_by("team_id") ), - teams_with_dashboard_shared_count=list( + "teams_with_dashboard_shared_count": list( Dashboard.objects.filter(sharingconfiguration__enabled=True) .values("team_id") .annotate(total=Count("id")) .order_by("team_id") ), - teams_with_dashboard_tagged_count=list( + "teams_with_dashboard_tagged_count": list( Dashboard.objects.filter(tagged_items__isnull=False) .values("team_id") .annotate(total=Count("id")) .order_by("team_id") ), - teams_with_ff_count=list(FeatureFlag.objects.values("team_id").annotate(total=Count("id")).order_by("team_id")), - teams_with_ff_active_count=list( + "teams_with_ff_count": list( + FeatureFlag.objects.values("team_id").annotate(total=Count("id")).order_by("team_id") + ), + "teams_with_ff_active_count": list( FeatureFlag.objects.filter(active=True).values("team_id").annotate(total=Count("id")).order_by("team_id") ), - teams_with_hogql_app_bytes_read=get_teams_with_hogql_metric( + "teams_with_hogql_app_bytes_read": get_teams_with_hogql_metric( period_start, period_end, metric="read_bytes", query_types=["hogql_query", "HogQLQuery"], access_method="", ), - teams_with_hogql_app_rows_read=get_teams_with_hogql_metric( + "teams_with_hogql_app_rows_read": get_teams_with_hogql_metric( period_start, period_end, metric="read_rows", query_types=["hogql_query", "HogQLQuery"], access_method="", ), - teams_with_hogql_app_duration_ms=get_teams_with_hogql_metric( + "teams_with_hogql_app_duration_ms": get_teams_with_hogql_metric( period_start, period_end, metric="query_duration_ms", query_types=["hogql_query", "HogQLQuery"], access_method="", ), - teams_with_hogql_api_bytes_read=get_teams_with_hogql_metric( + "teams_with_hogql_api_bytes_read": get_teams_with_hogql_metric( period_start, period_end, metric="read_bytes", query_types=["hogql_query", "HogQLQuery"], access_method="personal_api_key", ), - teams_with_hogql_api_rows_read=get_teams_with_hogql_metric( + "teams_with_hogql_api_rows_read": get_teams_with_hogql_metric( period_start, period_end, metric="read_rows", query_types=["hogql_query", "HogQLQuery"], access_method="personal_api_key", ), - teams_with_hogql_api_duration_ms=get_teams_with_hogql_metric( + "teams_with_hogql_api_duration_ms": get_teams_with_hogql_metric( period_start, period_end, metric="query_duration_ms", query_types=["hogql_query", "HogQLQuery"], access_method="personal_api_key", ), - teams_with_event_explorer_app_bytes_read=get_teams_with_hogql_metric( + "teams_with_event_explorer_app_bytes_read": get_teams_with_hogql_metric( period_start, period_end, metric="read_bytes", query_types=["EventsQuery"], access_method="", ), - teams_with_event_explorer_app_rows_read=get_teams_with_hogql_metric( + "teams_with_event_explorer_app_rows_read": get_teams_with_hogql_metric( period_start, period_end, metric="read_rows", query_types=["EventsQuery"], access_method="", ), - teams_with_event_explorer_app_duration_ms=get_teams_with_hogql_metric( + "teams_with_event_explorer_app_duration_ms": get_teams_with_hogql_metric( period_start, period_end, metric="query_duration_ms", query_types=["EventsQuery"], access_method="", ), - teams_with_event_explorer_api_bytes_read=get_teams_with_hogql_metric( + "teams_with_event_explorer_api_bytes_read": get_teams_with_hogql_metric( period_start, period_end, metric="read_bytes", query_types=["EventsQuery"], access_method="personal_api_key", ), - teams_with_event_explorer_api_rows_read=get_teams_with_hogql_metric( + "teams_with_event_explorer_api_rows_read": get_teams_with_hogql_metric( period_start, period_end, metric="read_rows", query_types=["EventsQuery"], access_method="personal_api_key", ), - teams_with_event_explorer_api_duration_ms=get_teams_with_hogql_metric( + "teams_with_event_explorer_api_duration_ms": get_teams_with_hogql_metric( period_start, period_end, metric="query_duration_ms", query_types=["EventsQuery"], access_method="personal_api_key", ), - teams_with_survey_responses_count_in_period=get_teams_with_survey_responses_count_in_period( + "teams_with_survey_responses_count_in_period": get_teams_with_survey_responses_count_in_period( period_start, period_end ), - teams_with_survey_responses_count_in_month=get_teams_with_survey_responses_count_in_period( + "teams_with_survey_responses_count_in_month": get_teams_with_survey_responses_count_in_period( period_start.replace(day=1), period_end ), - teams_with_rows_synced_in_period=get_teams_with_rows_synced_in_period(period_start, period_end), - ) + "teams_with_rows_synced_in_period": get_teams_with_rows_synced_in_period(period_start, period_end), + } def _get_all_usage_data_as_team_rows(period_start: datetime, period_end: datetime) -> Dict[str, Any]: diff --git a/posthog/tasks/verify_persons_data_in_sync.py b/posthog/tasks/verify_persons_data_in_sync.py index 406708beb6f5a..02a53b0176c7b 100644 --- a/posthog/tasks/verify_persons_data_in_sync.py +++ b/posthog/tasks/verify_persons_data_in_sync.py @@ -83,7 +83,7 @@ def verify_persons_data_in_sync( def _team_integrity_statistics(person_data: List[Any]) -> Counter: person_ids = [id for id, _, _ in person_data] person_uuids = [uuid for _, uuid, _ in person_data] - team_ids = list(set(team_id for _, _, team_id in person_data)) + team_ids = list({team_id for _, _, team_id in person_data}) # :TRICKY: To speed up processing, we fetch all models in batch at once and store results in dictionary indexed by person uuid pg_persons = _index_by( @@ -145,8 +145,8 @@ def _team_integrity_statistics(person_data: List[Any]) -> Counter: if ch_version != 0 and ch_version == pg_person.version and pg_person.properties != ch_properties: result["properties_mismatch_same_version"] += 1 - pg_distinct_ids = list(sorted(map(str, pg_person.distinct_ids))) - ch_distinct_id = list(sorted(str(distinct_id) for distinct_id, _ in ch_distinct_ids_mapping.get(uuid, []))) + pg_distinct_ids = sorted(map(str, pg_person.distinct_ids)) + ch_distinct_id = sorted(str(distinct_id) for distinct_id, _ in ch_distinct_ids_mapping.get(uuid, [])) if pg_distinct_ids != ch_distinct_id: result["distinct_ids_mismatch"] += 1 return result diff --git a/posthog/temporal/batch_exports/redshift_batch_export.py b/posthog/temporal/batch_exports/redshift_batch_export.py index bc1549cef838f..65ff6d10b36ac 100644 --- a/posthog/temporal/batch_exports/redshift_batch_export.py +++ b/posthog/temporal/batch_exports/redshift_batch_export.py @@ -64,7 +64,7 @@ def remove_escaped_whitespace_recursive(value): return type(value)(remove_escaped_whitespace_recursive(sequence_value) for sequence_value in sequence) # type: ignore case set(elements): - return set(remove_escaped_whitespace_recursive(element) for element in elements) + return {remove_escaped_whitespace_recursive(element) for element in elements} case {**mapping}: return {k: remove_escaped_whitespace_recursive(v) for k, v in mapping.items()} @@ -374,7 +374,7 @@ async def insert_into_redshift_activity(inputs: RedshiftInsertInputs) -> int: fields=table_fields, ) - schema_columns = set((field[0] for field in table_fields)) + schema_columns = {field[0] for field in table_fields} def map_to_record(row: dict) -> dict: """Map row to a record to insert to Redshift.""" diff --git a/posthog/temporal/data_imports/pipelines/hubspot/__init__.py b/posthog/temporal/data_imports/pipelines/hubspot/__init__.py index f23b305d00a13..3ffa3c8ffa161 100644 --- a/posthog/temporal/data_imports/pipelines/hubspot/__init__.py +++ b/posthog/temporal/data_imports/pipelines/hubspot/__init__.py @@ -110,7 +110,7 @@ def crm_objects( custom_props = [prop for prop in all_props if not prop.startswith("hs_")] props = props + custom_props # type: ignore - props = ",".join(sorted(list(set(props)))) + props = ",".join(sorted(set(props))) if len(props) > 10000: raise ValueError( diff --git a/posthog/temporal/data_imports/pipelines/hubspot/helpers.py b/posthog/temporal/data_imports/pipelines/hubspot/helpers.py index b724368fe7e40..0ef03b6db23d6 100644 --- a/posthog/temporal/data_imports/pipelines/hubspot/helpers.py +++ b/posthog/temporal/data_imports/pipelines/hubspot/helpers.py @@ -29,7 +29,7 @@ def _get_headers(api_key: str) -> Dict[str, str]: """ # Construct the dictionary of HTTP headers to use for API requests - return dict(authorization=f"Bearer {api_key}") + return {"authorization": f"Bearer {api_key}"} def extract_property_history(objects: List[Dict[str, Any]]) -> Iterator[Dict[str, Any]]: diff --git a/posthog/temporal/tests/batch_exports/test_batch_exports.py b/posthog/temporal/tests/batch_exports/test_batch_exports.py index 0afbfcabb71cb..9bc9c5969fad4 100644 --- a/posthog/temporal/tests/batch_exports/test_batch_exports.py +++ b/posthog/temporal/tests/batch_exports/test_batch_exports.py @@ -181,7 +181,7 @@ def assert_records_match_events(records, events): assert len(all_expected) == len(all_record) assert len([record["uuid"] for record in all_record]) == len( - set(record["uuid"] for record in all_record) + {record["uuid"] for record in all_record} ), "duplicate records found" for expected, record in zip(all_expected, all_record): @@ -667,7 +667,7 @@ def test_batch_export_temporary_file_write_records_to_csv(records): quoting=csv.QUOTE_NONE, ) - rows = [row for row in reader] + rows = list(reader) assert len(rows) == len(records) for row_index, csv_record in enumerate(rows): @@ -720,7 +720,7 @@ def test_batch_export_temporary_file_write_records_to_tsv(records): quoting=csv.QUOTE_NONE, ) - rows = [row for row in reader] + rows = list(reader) assert len(rows) == len(records) for row_index, csv_record in enumerate(rows): diff --git a/posthog/temporal/tests/batch_exports/test_http_batch_export_workflow.py b/posthog/temporal/tests/batch_exports/test_http_batch_export_workflow.py index 6267577472125..7369d0c791ba9 100644 --- a/posthog/temporal/tests/batch_exports/test_http_batch_export_workflow.py +++ b/posthog/temporal/tests/batch_exports/test_http_batch_export_workflow.py @@ -111,8 +111,8 @@ async def assert_clickhouse_records_in_mock_server( expected_records.append(expected_record) - inserted_column_names = [column_name for column_name in posted_records[0].keys()].sort() - expected_column_names = [column_name for column_name in expected_records[0].keys()].sort() + inserted_column_names = list(posted_records[0].keys()).sort() + expected_column_names = list(expected_records[0].keys()).sort() assert inserted_column_names == expected_column_names assert posted_records[0] == expected_records[0] diff --git a/posthog/temporal/tests/batch_exports/test_postgres_batch_export_workflow.py b/posthog/temporal/tests/batch_exports/test_postgres_batch_export_workflow.py index c486cc2747fcc..d8913f4dccbdd 100644 --- a/posthog/temporal/tests/batch_exports/test_postgres_batch_export_workflow.py +++ b/posthog/temporal/tests/batch_exports/test_postgres_batch_export_workflow.py @@ -122,8 +122,8 @@ async def assert_clickhouse_records_in_postgres( expected_records.append(expected_record) - inserted_column_names = [column_name for column_name in inserted_records[0].keys()].sort() - expected_column_names = [column_name for column_name in expected_records[0].keys()].sort() + inserted_column_names = list(inserted_records[0].keys()).sort() + expected_column_names = list(expected_records[0].keys()).sort() assert inserted_column_names == expected_column_names assert inserted_records[0] == expected_records[0] diff --git a/posthog/temporal/tests/batch_exports/test_redshift_batch_export_workflow.py b/posthog/temporal/tests/batch_exports/test_redshift_batch_export_workflow.py index 173bed3a69bb3..69413dcab6026 100644 --- a/posthog/temporal/tests/batch_exports/test_redshift_batch_export_workflow.py +++ b/posthog/temporal/tests/batch_exports/test_redshift_batch_export_workflow.py @@ -135,8 +135,8 @@ async def assert_clickhouse_records_in_redshfit( expected_records.append(expected_record) - inserted_column_names = [column_name for column_name in inserted_records[0].keys()].sort() - expected_column_names = [column_name for column_name in expected_records[0].keys()].sort() + inserted_column_names = list(inserted_records[0].keys()).sort() + expected_column_names = list(expected_records[0].keys()).sort() inserted_records.sort(key=operator.itemgetter("event")) expected_records.sort(key=operator.itemgetter("event")) diff --git a/posthog/temporal/tests/batch_exports/test_snowflake_batch_export_workflow.py b/posthog/temporal/tests/batch_exports/test_snowflake_batch_export_workflow.py index f8c12a3d1369f..21ac833944e9d 100644 --- a/posthog/temporal/tests/batch_exports/test_snowflake_batch_export_workflow.py +++ b/posthog/temporal/tests/batch_exports/test_snowflake_batch_export_workflow.py @@ -877,8 +877,8 @@ def assert_clickhouse_records_in_snowflake( expected_records.append(expected_record) - inserted_column_names = [column_name for column_name in inserted_records[0].keys()].sort() - expected_column_names = [column_name for column_name in expected_records[0].keys()].sort() + inserted_column_names = list(inserted_records[0].keys()).sort() + expected_column_names = list(expected_records[0].keys()).sort() # Ordering is not guaranteed, so we sort before comparing. inserted_records.sort(key=operator.itemgetter("event")) diff --git a/posthog/temporal/tests/persons_on_events_squash/test_squash_person_overrides_workflow.py b/posthog/temporal/tests/persons_on_events_squash/test_squash_person_overrides_workflow.py index 2010b13345aee..7c2e56aee6d08 100644 --- a/posthog/temporal/tests/persons_on_events_squash/test_squash_person_overrides_workflow.py +++ b/posthog/temporal/tests/persons_on_events_squash/test_squash_person_overrides_workflow.py @@ -461,7 +461,7 @@ async def assert_events_have_been_overriden(overriden_events, person_overrides): query_parameters={"uuid": event["uuid"]}, ) row = response.decode("utf-8").splitlines()[0] - values = [value for value in row.split("\t")] + values = list(row.split("\t")) new_event = { "uuid": UUID(values[0]), "event": values[1], @@ -598,7 +598,7 @@ async def test_update_events_with_person_overrides_mutation_dry_run( query_parameters={"uuid": event["uuid"]}, ) row = response.decode("utf-8").splitlines()[0] - values = [value for value in row.split("\t")] + values = list(row.split("\t")) new_event = { "uuid": UUID(values[0]), "event": values[1], diff --git a/posthog/test/base.py b/posthog/test/base.py index 8e914dd2b59d5..5f8d3e2b7f10f 100644 --- a/posthog/test/base.py +++ b/posthog/test/base.py @@ -95,9 +95,9 @@ def _setup_test_data(klass): klass.organization = Organization.objects.create(name=klass.CONFIG_ORGANIZATION_NAME) klass.project, klass.team = Project.objects.create_with_team( organization=klass.organization, - team_fields=dict( - api_token=klass.CONFIG_API_TOKEN, - test_account_filters=[ + team_fields={ + "api_token": klass.CONFIG_API_TOKEN, + "test_account_filters": [ { "key": "email", "value": "@posthog.com", @@ -105,8 +105,8 @@ def _setup_test_data(klass): "type": "person", } ], - has_completed_onboarding_for={"product_analytics": True}, - ), + "has_completed_onboarding_for": {"product_analytics": True}, + }, ) if klass.CONFIG_EMAIL: klass.user = User.objects.create_and_join(klass.organization, klass.CONFIG_EMAIL, klass.CONFIG_PASSWORD) @@ -409,9 +409,9 @@ def cleanup_materialized_columns(): def also_test_with_materialized_columns( - event_properties=[], - person_properties=[], - group_properties=[], + event_properties=None, + person_properties=None, + group_properties=None, verify_no_jsonextract=True, # :TODO: Remove this when groups-on-events is released materialize_only_with_person_on_events=False, @@ -422,6 +422,12 @@ def also_test_with_materialized_columns( Requires a unittest class with ClickhouseTestMixin mixed in """ + if group_properties is None: + group_properties = [] + if person_properties is None: + person_properties = [] + if event_properties is None: + event_properties = [] try: from ee.clickhouse.materialized_columns.analyze import materialize except: diff --git a/posthog/test/test_journeys.py b/posthog/test/test_journeys.py index 6e2122c3b5da9..0e535437076e9 100644 --- a/posthog/test/test_journeys.py +++ b/posthog/test/test_journeys.py @@ -77,37 +77,37 @@ def journeys_for( event["timestamp"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f") events_to_create.append( - dict( - event_uuid=UUID(event["event_uuid"]) if "event_uuid" in event else uuid4(), - team=team, - distinct_id=distinct_id, - event=event["event"], - timestamp=event["timestamp"], - properties=event.get("properties", {}), - person_id=people[distinct_id].uuid, - person_properties=people[distinct_id].properties or {}, - person_created_at=people[distinct_id].created_at, - group0_properties=event.get("group0_properties", {}) + { + "event_uuid": UUID(event["event_uuid"]) if "event_uuid" in event else uuid4(), + "team": team, + "distinct_id": distinct_id, + "event": event["event"], + "timestamp": event["timestamp"], + "properties": event.get("properties", {}), + "person_id": people[distinct_id].uuid, + "person_properties": people[distinct_id].properties or {}, + "person_created_at": people[distinct_id].created_at, + "group0_properties": event.get("group0_properties", {}) or getattr(group_mapping.get("group0", {}), "group_properties", {}), - group1_properties=event.get("group1_properties", {}) + "group1_properties": event.get("group1_properties", {}) or getattr(group_mapping.get("group1", {}), "group_properties", {}), - group2_properties=event.get("group2_properties", {}) + "group2_properties": event.get("group2_properties", {}) or getattr(group_mapping.get("group2", {}), "group_properties", {}), - group3_properties=event.get("group3_properties", {}) + "group3_properties": event.get("group3_properties", {}) or getattr(group_mapping.get("group3", {}), "group_properties", {}), - group4_properties=event.get("group4_properties", {}) + "group4_properties": event.get("group4_properties", {}) or getattr(group_mapping.get("group4", {}), "group_properties", {}), - group0_created_at=event.get("group0_created_at") + "group0_created_at": event.get("group0_created_at") or getattr(group_mapping.get("group0", {}), "created_at", None), - group1_created_at=event.get("group1_created_at") + "group1_created_at": event.get("group1_created_at") or getattr(group_mapping.get("group1", {}), "created_at", None), - group2_created_at=event.get("group2_created_at") + "group2_created_at": event.get("group2_created_at") or getattr(group_mapping.get("group2", {}), "created_at", None), - group3_created_at=event.get("group3_created_at") + "group3_created_at": event.get("group3_created_at") or getattr(group_mapping.get("group3", {}), "created_at", None), - group4_created_at=event.get("group4_created_at") + "group4_created_at": event.get("group4_created_at") or getattr(group_mapping.get("group4", {}), "created_at", None), - ) + } ) _create_all_events_raw(events_to_create) diff --git a/posthog/test/test_migration_0273.py b/posthog/test/test_migration_0273.py index 3ce270f54540c..2674aa3b12658 100644 --- a/posthog/test/test_migration_0273.py +++ b/posthog/test/test_migration_0273.py @@ -172,9 +172,9 @@ def test_migration(self): entries = ActivityLog.objects.filter(activity="export_fail", is_system=True) - self.assertEqual(set(entry.detail["trigger"]["job_id"] for entry in entries), {"1", "6"}) + self.assertEqual({entry.detail["trigger"]["job_id"] for entry in entries}, {"1", "6"}) self.assertEqual( - set(entry.detail["trigger"]["failure_reason"] for entry in entries), + {entry.detail["trigger"]["failure_reason"] for entry in entries}, {"Export was killed after too much inactivity"}, ) diff --git a/posthog/test/test_migration_0385.py b/posthog/test/test_migration_0385.py index 3526b237fdeb2..6617b8e919e98 100644 --- a/posthog/test/test_migration_0385.py +++ b/posthog/test/test_migration_0385.py @@ -34,9 +34,7 @@ def test_migrate_to_create_session_recordings(self): Team = apps.get_model("posthog", "Team") - assert [ - x for x in Team.objects.all().values_list("name", "autocapture_exceptions_opt_in").order_by("name") - ] == [ + assert list(Team.objects.all().values_list("name", "autocapture_exceptions_opt_in").order_by("name")) == [ # unchanged ("t1", None), # set to False diff --git a/posthog/user_permissions.py b/posthog/user_permissions.py index a8c89573257a7..30a6bfca298b1 100644 --- a/posthog/user_permissions.py +++ b/posthog/user_permissions.py @@ -127,7 +127,7 @@ def preloaded_insight_dashboards(self) -> Optional[List[Dashboard]]: if self._tiles is None: return None - dashboard_ids = set(tile.dashboard_id for tile in self._tiles) + dashboard_ids = {tile.dashboard_id for tile in self._tiles} return list(Dashboard.objects.filter(pk__in=dashboard_ids)) def reset_insights_dashboard_cached_results(self): diff --git a/posthog/utils.py b/posthog/utils.py index 111ed0237cbcd..aaf4a3b27b3b0 100644 --- a/posthog/utils.py +++ b/posthog/utils.py @@ -274,7 +274,7 @@ def get_js_url(request: HttpRequest) -> str: def render_template( template_name: str, request: HttpRequest, - context: Dict = {}, + context: Dict = None, *, team_for_public_context: Optional["Team"] = None, ) -> HttpResponse: @@ -283,6 +283,8 @@ def render_template( If team_for_public_context is provided, this means this is a public page such as a shared dashboard. """ + if context is None: + context = {} template = get_template(template_name) context["opt_out_capture"] = settings.OPT_OUT_CAPTURE diff --git a/pyproject.toml b/pyproject.toml index a4fffb70b1853..4e495ab94f859 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,19 +15,10 @@ exclude = [ "./posthog/hogql/grammar", ] ignore = [ - "B006", - "B011", "B017", "B019", - "B024", "B904", "B905", - "C401", - "C408", - "C413", - "C414", - "C416", - "C417", "C901", "E501", "E722",