From 93f78a6fb2256151b87ed970fbcacc39b2249289 Mon Sep 17 00:00:00 2001 From: Julian Bez Date: Wed, 21 Aug 2024 12:40:50 +0200 Subject: [PATCH 1/6] Upgrade ruff and mypy --- mypy-baseline.txt | 70 +++++++++++++++++-- posthog/api/instance_settings.py | 6 +- .../models/external_table_definitions.py | 2 +- requirements-dev.in | 4 +- requirements-dev.txt | 3 +- 5 files changed, 71 insertions(+), 14 deletions(-) diff --git a/mypy-baseline.txt b/mypy-baseline.txt index e4f51c238f14e..340ac998bcdad 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -1,6 +1,7 @@ posthog/temporal/common/utils.py:0: error: Argument 1 to "abstractclassmethod" has incompatible type "Callable[[HeartbeatDetails, Any], Any]"; expected "Callable[[type[Never], Any], Any]" [arg-type] posthog/temporal/common/utils.py:0: note: This is likely because "from_activity" has named arguments: "cls". Consider marking them positional-only posthog/temporal/common/utils.py:0: error: Argument 2 to "__get__" of "classmethod" has incompatible type "type[HeartbeatType]"; expected "type[Never]" [arg-type] +posthog/tasks/exports/ordered_csv_renderer.py:0: error: No return value expected [return-value] posthog/warehouse/models/ssh_tunnel.py:0: error: Incompatible types in assignment (expression has type "NoEncryption", variable has type "BestAvailableEncryption") [assignment] posthog/temporal/data_imports/pipelines/sql_database/helpers.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Dict entry 2 has incompatible type "Literal['auto']": "None"; expected "Literal['json_response', 'header_link', 'auto', 'single_page', 'cursor', 'offset', 'page_number']": "type[BasePaginator]" [dict-item] @@ -66,6 +67,10 @@ posthog/plugins/utils.py:0: error: Statement is unreachable [unreachable] posthog/clickhouse/kafka_engine.py:0: error: Import cycle from Django settings module prevents type inference for 'KAFKA_HOSTS_FOR_CLICKHOUSE' [misc] posthog/utils.py:0: error: Import cycle from Django settings module prevents type inference for 'PERSISTED_FEATURE_FLAGS' [misc] posthog/utils.py:0: error: Import cycle from Django settings module prevents type inference for 'OBJECT_STORAGE_ENABLED' [misc] +posthog/utils.py:0: error: No overload variant of "asdict" matches argument type "type[DataclassInstance]" [call-overload] +posthog/utils.py:0: note: Possible overload variants: +posthog/utils.py:0: note: def asdict(obj: DataclassInstance) -> dict[str, Any] +posthog/utils.py:0: note: def [_T] asdict(obj: DataclassInstance, *, dict_factory: Callable[[list[tuple[str, Any]]], _T]) -> _T posthog/utils.py:0: error: Name "timezone.datetime" is not defined [name-defined] posthog/utils.py:0: error: Import cycle from Django settings module prevents type inference for 'DECIDE_TRACK_TEAM_IDS' [misc] posthog/models/dashboard.py:0: error: Need type annotation for "insights" [var-annotated] @@ -232,6 +237,11 @@ posthog/hogql/printer.py:0: error: "FieldOrTable" has no attribute "name" [attr posthog/hogql/printer.py:0: error: "FieldOrTable" has no attribute "name" [attr-defined] posthog/hogql/printer.py:0: error: Argument 2 to "_get_materialized_column" of "_Printer" has incompatible type "str | int"; expected "str" [arg-type] posthog/hogql/printer.py:0: error: Argument 1 to "_print_identifier" of "_Printer" has incompatible type "str | None"; expected "str" [arg-type] +posthog/api/documentation.py:0: error: Signature of "run_validation" incompatible with supertype "Field" [override] +posthog/api/documentation.py:0: note: Superclass: +posthog/api/documentation.py:0: note: def run_validation(self, data: Any = ...) -> Any +posthog/api/documentation.py:0: note: Subclass: +posthog/api/documentation.py:0: note: def run_validation(self, data: Any) -> Any posthog/api/action.py:0: error: Argument 1 to has incompatible type "*tuple[str, ...]"; expected "type[BaseRenderer]" [arg-type] posthog/test/base.py:0: error: Module has no attribute "configure" [attr-defined] posthog/test/base.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Organization") [assignment] @@ -366,6 +376,18 @@ posthog/hogql/test/test_timings.py:0: error: No overload variant of "__setitem__ posthog/hogql/test/test_timings.py:0: note: Possible overload variants: posthog/hogql/test/test_timings.py:0: note: def __setitem__(self, SupportsIndex, int, /) -> None posthog/hogql/test/test_timings.py:0: note: def __setitem__(self, slice, Iterable[int], /) -> None +posthog/hogql/test/test_timings.py:0: error: Signature of "assertAlmostEquals" incompatible with supertype "TestCase" [override] +posthog/hogql/test/test_timings.py:0: note: Superclass: +posthog/hogql/test/test_timings.py:0: note: @overload +posthog/hogql/test/test_timings.py:0: note: def [_S: SupportsSub[Any, Any]] assertAlmostEqual(self: TestCase, first: _S, second: _S, places: None, msg: Any, delta: _SupportsAbsAndDunderGE) -> None +posthog/hogql/test/test_timings.py:0: note: @overload +posthog/hogql/test/test_timings.py:0: note: def [_S: SupportsSub[Any, Any]] assertAlmostEqual(self: TestCase, first: _S, second: _S, places: None = ..., msg: Any = ..., *, delta: _SupportsAbsAndDunderGE) -> None +posthog/hogql/test/test_timings.py:0: note: @overload +posthog/hogql/test/test_timings.py:0: note: def [_T] assertAlmostEqual(self: TestCase, first: SupportsSub[_T, SupportsAbs[SupportsRound[object]]], second: _T, places: int | None = ..., msg: Any = ..., delta: None = ...) -> None +posthog/hogql/test/test_timings.py:0: note: @overload +posthog/hogql/test/test_timings.py:0: note: def [_T] assertAlmostEqual(self: TestCase, first: _T, second: SupportsRSub[_T, SupportsAbs[SupportsRound[object]]], places: int | None = ..., msg: Any = ..., delta: None = ...) -> None +posthog/hogql/test/test_timings.py:0: note: Subclass: +posthog/hogql/test/test_timings.py:0: note: def assertAlmostEquals(self, a: Any, b: Any, epsilon: Any = ...) -> Any posthog/hogql/test/test_resolver.py:0: error: Item "None" of "JoinExpr | None" has no attribute "next_join" [union-attr] posthog/hogql/test/test_resolver.py:0: error: Item "None" of "JoinExpr | Any | None" has no attribute "constraint" [union-attr] posthog/hogql/test/test_resolver.py:0: error: Item "None" of "JoinConstraint | Any | None" has no attribute "constraint_type" [union-attr] @@ -415,8 +437,8 @@ posthog/hogql/functions/test/test_cohort.py:0: error: "TestCohort" has no attrib posthog/hogql/database/schema/event_sessions.py:0: error: Statement is unreachable [unreachable] posthog/hogql/ai.py:0: error: No overload variant of "__getitem__" of "tuple" matches argument type "str" [call-overload] posthog/hogql/ai.py:0: note: Possible overload variants: -posthog/hogql/ai.py:0: note: def __getitem__(self, SupportsIndex, /) -> Any -posthog/hogql/ai.py:0: note: def __getitem__(self, slice, /) -> tuple[Any, ...] +posthog/hogql/ai.py:0: note: def __getitem__(self, SupportsIndex, /) -> str | Any +posthog/hogql/ai.py:0: note: def __getitem__(self, slice, /) -> tuple[str | Any, ...] posthog/heatmaps/test/test_heatmaps_api.py:0: error: "HttpResponse" has no attribute "json" [attr-defined] posthog/heatmaps/test/test_heatmaps_api.py:0: error: "HttpResponse" has no attribute "json" [attr-defined] posthog/heatmaps/test/test_heatmaps_api.py:0: error: "HttpResponse" has no attribute "json" [attr-defined] @@ -431,6 +453,16 @@ posthog/api/test/test_signup.py:0: error: Module "django.utils.timezone" does no posthog/api/test/test_preflight.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/api/test/test_preflight.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/api/test/test_person.py:0: error: Argument "data" to "get" of "APIClient" has incompatible type "dict[str, object]"; expected "Mapping[str, str | bytes | int | Iterable[str | bytes | int]] | Iterable[tuple[str, str | bytes | int | Iterable[str | bytes | int]]] | None" [arg-type] +posthog/api/organization_member.py:0: error: Signature of "update" incompatible with supertype "ModelSerializer" [override] +posthog/api/organization_member.py:0: note: Superclass: +posthog/api/organization_member.py:0: note: def update(self, instance: Any, validated_data: Any) -> Any +posthog/api/organization_member.py:0: note: Subclass: +posthog/api/organization_member.py:0: note: def update(self, updated_membership: Any, validated_data: Any, **kwargs: Any) -> Any +posthog/api/organization_member.py:0: error: Signature of "update" incompatible with supertype "BaseSerializer" [override] +posthog/api/organization_member.py:0: note: Superclass: +posthog/api/organization_member.py:0: note: def update(self, instance: Any, validated_data: Any) -> Any +posthog/api/organization_member.py:0: note: Subclass: +posthog/api/organization_member.py:0: note: def update(self, updated_membership: Any, validated_data: Any, **kwargs: Any) -> Any posthog/api/notebook.py:0: error: Incompatible types in assignment (expression has type "int", variable has type "str | None") [assignment] posthog/warehouse/data_load/validate_schema.py:0: error: Incompatible types in assignment (expression has type "dict[str, dict[str, str | bool]] | dict[str, str]", variable has type "dict[str, dict[str, str]]") [assignment] posthog/temporal/data_imports/workflow_activities/create_job_model.py:0: error: Incompatible types in assignment (expression has type "list[str]", variable has type "dict[str, list[tuple[str, str]]]") [assignment] @@ -514,10 +546,6 @@ posthog/hogql/database/test/test_s3_table.py:0: error: Argument "dialect" to "pr posthog/api/test/dashboards/test_dashboard.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] posthog/api/test/dashboards/test_dashboard.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] posthog/api/test/dashboards/test_dashboard.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] -posthog/api/test/dashboards/test_dashboard.py:0: error: Argument 1 to "soft_delete" of "DashboardAPI" has incompatible type "int | _FieldDescriptor[AutoField[Combinable | int | str | None, int]] | Any"; expected "int" [arg-type] -posthog/api/test/dashboards/test_dashboard.py:0: error: Argument 1 to "get_dashboard" of "DashboardAPI" has incompatible type "int | _FieldDescriptor[AutoField[Combinable | int | str | None, int]] | Any"; expected "int" [arg-type] -posthog/api/test/dashboards/test_dashboard.py:0: error: Argument 1 to "update_dashboard" of "DashboardAPI" has incompatible type "int | _FieldDescriptor[AutoField[Combinable | int | str | None, int]] | Any"; expected "int" [arg-type] -posthog/api/test/dashboards/test_dashboard.py:0: error: Argument 1 to "get_dashboard" of "DashboardAPI" has incompatible type "int | _FieldDescriptor[AutoField[Combinable | int | str | None, int]] | Any"; expected "int" [arg-type] posthog/api/search.py:0: error: Argument "klass" to "class_queryset" has incompatible type "object"; expected "type[Model]" [arg-type] posthog/api/search.py:0: error: Argument "search_fields" to "class_queryset" has incompatible type "object"; expected "dict[str, str]" [arg-type] posthog/api/search.py:0: error: Argument "extra_fields" to "class_queryset" has incompatible type "object"; expected "dict[Any, Any] | None" [arg-type] @@ -541,6 +569,31 @@ posthog/api/property_definition.py:0: error: Incompatible types in assignment (e posthog/api/property_definition.py:0: error: Item "AnonymousUser" of "User | AnonymousUser" has no attribute "organization" [union-attr] posthog/api/property_definition.py:0: error: Item "None" of "Organization | Any | None" has no attribute "is_feature_available" [union-attr] posthog/api/event.py:0: error: Argument 1 to has incompatible type "*tuple[str, ...]"; expected "type[BaseRenderer]" [arg-type] +posthog/admin/inlines/plugin_attachment_inline.py:0: error: Signature of "has_add_permission" incompatible with supertype "BaseModelAdmin" [override] +posthog/admin/inlines/plugin_attachment_inline.py:0: note: Superclass: +posthog/admin/inlines/plugin_attachment_inline.py:0: note: def has_add_permission(self, request: HttpRequest) -> bool +posthog/admin/inlines/plugin_attachment_inline.py:0: note: Subclass: +posthog/admin/inlines/plugin_attachment_inline.py:0: note: def has_add_permission(self, request: Any, obj: Any) -> Any +posthog/admin/inlines/plugin_attachment_inline.py:0: error: Signature of "has_change_permission" incompatible with supertype "InlineModelAdmin" [override] +posthog/admin/inlines/plugin_attachment_inline.py:0: note: Superclass: +posthog/admin/inlines/plugin_attachment_inline.py:0: note: def has_change_permission(self, request: HttpRequest, obj: Any | None = ...) -> bool +posthog/admin/inlines/plugin_attachment_inline.py:0: note: Subclass: +posthog/admin/inlines/plugin_attachment_inline.py:0: note: def has_change_permission(self, request: Any, obj: Any) -> Any +posthog/admin/inlines/plugin_attachment_inline.py:0: error: Signature of "has_change_permission" incompatible with supertype "BaseModelAdmin" [override] +posthog/admin/inlines/plugin_attachment_inline.py:0: note: Superclass: +posthog/admin/inlines/plugin_attachment_inline.py:0: note: def has_change_permission(self, request: HttpRequest, obj: Any | None = ...) -> bool +posthog/admin/inlines/plugin_attachment_inline.py:0: note: Subclass: +posthog/admin/inlines/plugin_attachment_inline.py:0: note: def has_change_permission(self, request: Any, obj: Any) -> Any +posthog/admin/inlines/plugin_attachment_inline.py:0: error: Signature of "has_delete_permission" incompatible with supertype "InlineModelAdmin" [override] +posthog/admin/inlines/plugin_attachment_inline.py:0: note: Superclass: +posthog/admin/inlines/plugin_attachment_inline.py:0: note: def has_delete_permission(self, request: HttpRequest, obj: Any | None = ...) -> bool +posthog/admin/inlines/plugin_attachment_inline.py:0: note: Subclass: +posthog/admin/inlines/plugin_attachment_inline.py:0: note: def has_delete_permission(self, request: Any, obj: Any) -> Any +posthog/admin/inlines/plugin_attachment_inline.py:0: error: Signature of "has_delete_permission" incompatible with supertype "BaseModelAdmin" [override] +posthog/admin/inlines/plugin_attachment_inline.py:0: note: Superclass: +posthog/admin/inlines/plugin_attachment_inline.py:0: note: def has_delete_permission(self, request: HttpRequest, obj: Any | None = ...) -> bool +posthog/admin/inlines/plugin_attachment_inline.py:0: note: Subclass: +posthog/admin/inlines/plugin_attachment_inline.py:0: note: def has_delete_permission(self, request: Any, obj: Any) -> Any posthog/temporal/tests/batch_exports/test_run_updates.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/tests/batch_exports/test_run_updates.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/tests/batch_exports/test_run_updates.py:0: error: Unused "type: ignore" comment [unused-ignore] @@ -590,6 +643,11 @@ posthog/warehouse/external_data_source/source.py:0: error: Incompatible types in posthog/warehouse/external_data_source/source.py:0: error: Incompatible types in assignment (expression has type "dict[str, Collection[str]]", variable has type "StripeSourcePayload") [assignment] posthog/warehouse/external_data_source/source.py:0: error: Argument 1 to "_create_source" has incompatible type "StripeSourcePayload"; expected "dict[Any, Any]" [arg-type] posthog/temporal/tests/batch_exports/test_redshift_batch_export_workflow.py:0: error: Incompatible types in assignment (expression has type "str | int", variable has type "int") [assignment] +posthog/api/test/batch_exports/conftest.py:0: error: Signature of "run" incompatible with supertype "Worker" [override] +posthog/api/test/batch_exports/conftest.py:0: note: Superclass: +posthog/api/test/batch_exports/conftest.py:0: note: def run(self) -> Coroutine[Any, Any, None] +posthog/api/test/batch_exports/conftest.py:0: note: Subclass: +posthog/api/test/batch_exports/conftest.py:0: note: def run(self, loop: Any) -> Any posthog/api/test/batch_exports/conftest.py:0: error: Argument "activities" to "ThreadedWorker" has incompatible type "list[function]"; expected "Sequence[Callable[..., Any]]" [arg-type] posthog/temporal/tests/data_imports/test_end_to_end.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/api/test/test_team.py:0: error: "HttpResponse" has no attribute "json" [attr-defined] diff --git a/posthog/api/instance_settings.py b/posthog/api/instance_settings.py index 13c1461ba5655..f7c8572919a3d 100644 --- a/posthog/api/instance_settings.py +++ b/posthog/api/instance_settings.py @@ -21,10 +21,10 @@ def cast_str_to_desired_type(str_value: str, target_type: type) -> Any: - if target_type == int: + if target_type is int: return int(str_value) - if target_type == bool: + if target_type is bool: return str_to_bool(str_value) return str_value @@ -81,7 +81,7 @@ def update(self, instance: InstanceSettingHelper, validated_data: dict[str, Any] raise serializers.ValidationError({"value": "This field is required."}, code="required") target_type: type = CONSTANCE_CONFIG[instance.key][2] - if target_type == bool and isinstance(validated_data["value"], bool): + if target_type is bool and isinstance(validated_data["value"], bool): new_value_parsed = validated_data["value"] else: new_value_parsed = cast_str_to_desired_type(validated_data["value"], target_type) diff --git a/posthog/warehouse/models/external_table_definitions.py b/posthog/warehouse/models/external_table_definitions.py index 62d0289f74f59..0d8e49fa4dca7 100644 --- a/posthog/warehouse/models/external_table_definitions.py +++ b/posthog/warehouse/models/external_table_definitions.py @@ -657,5 +657,5 @@ def get_dlt_mapping_for_external_table(table): "nullable": True, } for _, field in external_tables[table].items() - if type(field) != ast.ExpressionField + if type(field) is not ast.ExpressionField } diff --git a/requirements-dev.in b/requirements-dev.in index 5ca5431dbaf1c..d76b0a055cb86 100644 --- a/requirements-dev.in +++ b/requirements-dev.in @@ -11,8 +11,8 @@ -c requirements.txt -ruff~=0.4.10 -mypy~=1.10.0 +ruff~=0.6.1 +mypy~=1.11.1 mypy-baseline~=0.7.0 mypy-extensions==1.0.0 datamodel-code-generator==0.25.6 diff --git a/requirements-dev.txt b/requirements-dev.txt index 938eaead5395c..e61940bab377d 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -155,8 +155,7 @@ multidict==6.0.2 # -c requirements.txt # aiohttp # yarl -mypy==1.10.0 - # via -r requirements-dev.in +mypy==1.11.1 mypy-baseline==0.7.0 # via -r requirements-dev.in mypy-boto3-s3==1.34.65 From cca585e4b230c15443700639a2d3d9336dae0c36 Mon Sep 17 00:00:00 2001 From: Julian Bez Date: Wed, 21 Aug 2024 12:46:47 +0200 Subject: [PATCH 2/6] Upgrade Django stubs and remove type annotations for model fields --- ee/models/dashboard_privilege.py | 12 +- ee/models/event_definition.py | 8 +- ee/models/explicit_team_membership.py | 12 +- ee/models/feature_flag_role_access.py | 8 +- ee/models/license.py | 10 +- ee/models/organization_resource_access.py | 16 +- ee/models/property_definition.py | 8 +- ee/models/role.py | 20 +- mypy-baseline.txt | 435 ++++++++++++++---- posthog/batch_exports/models.py | 68 ++- posthog/models/_deprecated_prompts.py | 46 +- posthog/models/action/action.py | 30 +- posthog/models/action/action_step.py | 24 +- .../models/activity_logging/activity_log.py | 5 +- .../activity_logging/notification_viewed.py | 2 +- posthog/models/alert.py | 10 +- posthog/models/annotation.py | 26 +- .../models/async_deletion/async_deletion.py | 18 +- posthog/models/async_migration.py | 38 +- posthog/models/cohort/cohort.py | 48 +- posthog/models/comment.py | 14 +- posthog/models/dashboard.py | 28 +- posthog/models/dashboard_templates.py | 24 +- posthog/models/dashboard_tile.py | 26 +- posthog/models/early_access_feature.py | 14 +- posthog/models/element/element.py | 20 +- posthog/models/element_group.py | 4 +- .../models/error_tracking/error_tracking.py | 10 +- posthog/models/event/event.py | 18 +- posthog/models/event_buffer.py | 6 +- posthog/models/event_definition.py | 12 +- posthog/models/event_property.py | 6 +- posthog/models/experiment.py | 30 +- posthog/models/exported_asset.py | 22 +- posthog/models/feature_flag/feature_flag.py | 56 ++- posthog/models/feedback/survey.py | 32 +- posthog/models/group/group.py | 16 +- posthog/models/group_type_mapping.py | 10 +- posthog/models/hog_functions/hog_function.py | 34 +- posthog/models/insight.py | 64 +-- posthog/models/insight_caching_state.py | 16 +- posthog/models/instance_setting.py | 4 +- posthog/models/integration.py | 16 +- posthog/models/messaging.py | 10 +- posthog/models/notebook/notebook.py | 20 +- posthog/models/organization.py | 46 +- posthog/models/organization_domain.py | 20 +- posthog/models/organization_invite.py | 20 +- posthog/models/person/person.py | 44 +- posthog/models/personal_api_key.py | 14 +- posthog/models/plugin.py | 110 +++-- posthog/models/project.py | 8 +- posthog/models/property_definition.py | 14 +- posthog/models/proxy_record.py | 18 +- posthog/models/scheduled_change.py | 18 +- posthog/models/sharing_configuration.py | 10 +- posthog/models/subscription.py | 28 +- posthog/models/tag.py | 4 +- posthog/models/tagged_item.py | 14 +- posthog/models/team/team.py | 102 ++-- posthog/models/uploaded_media.py | 12 +- posthog/models/user.py | 28 +- posthog/models/user_scene_personalisation.py | 8 +- posthog/models/utils.py | 14 +- .../models/session_recording.py | 38 +- .../models/session_recording_event.py | 22 +- .../models/session_recording_playlist.py | 26 +- .../models/session_recording_playlist_item.py | 10 +- posthog/warehouse/models/credential.py | 2 +- .../models/datawarehouse_saved_query.py | 12 +- posthog/warehouse/models/external_data_job.py | 24 +- .../warehouse/models/external_data_schema.py | 30 +- .../warehouse/models/external_data_source.py | 18 +- posthog/warehouse/models/join.py | 22 +- posthog/warehouse/models/table.py | 22 +- pyproject.toml | 2 +- requirements-dev.in | 2 +- requirements-dev.txt | 13 +- requirements.txt | 2 +- 79 files changed, 1149 insertions(+), 984 deletions(-) diff --git a/ee/models/dashboard_privilege.py b/ee/models/dashboard_privilege.py index 40c48ec9ca9d2..4dde1f4d13e95 100644 --- a/ee/models/dashboard_privilege.py +++ b/ee/models/dashboard_privilege.py @@ -6,23 +6,21 @@ # We call models that grant a user access to some resource (which isn't a grouping of users) a "privilege" class DashboardPrivilege(UUIDModel): - dashboard: models.ForeignKey = models.ForeignKey( + dashboard = models.ForeignKey( "posthog.Dashboard", on_delete=models.CASCADE, related_name="privileges", related_query_name="privilege", ) - user: models.ForeignKey = models.ForeignKey( + user = models.ForeignKey( "posthog.User", on_delete=models.CASCADE, related_name="explicit_dashboard_privileges", related_query_name="explicit_dashboard_privilege", ) - level: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField( - choices=Dashboard.RestrictionLevel.choices - ) - added_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) + level = models.PositiveSmallIntegerField(choices=Dashboard.RestrictionLevel.choices) + added_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) class Meta: constraints = [ diff --git a/ee/models/event_definition.py b/ee/models/event_definition.py index 408fbcec43cf5..fc172c4ac3c8f 100644 --- a/ee/models/event_definition.py +++ b/ee/models/event_definition.py @@ -11,11 +11,11 @@ class EnterpriseEventDefinition(EventDefinition): on_delete=models.SET_NULL, related_name="event_definitions", ) - description: models.TextField = models.TextField(blank=True, null=True, default="") - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) + description = models.TextField(blank=True, null=True, default="") + updated_at = models.DateTimeField(auto_now=True) updated_by = models.ForeignKey("posthog.User", null=True, on_delete=models.SET_NULL, blank=True) - verified: models.BooleanField = models.BooleanField(default=False, blank=True) - verified_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) + verified = models.BooleanField(default=False, blank=True) + verified_at = models.DateTimeField(null=True, blank=True) verified_by = models.ForeignKey( "posthog.User", null=True, diff --git a/ee/models/explicit_team_membership.py b/ee/models/explicit_team_membership.py index 2e41101cb3b6c..35330a11bbb73 100644 --- a/ee/models/explicit_team_membership.py +++ b/ee/models/explicit_team_membership.py @@ -12,23 +12,21 @@ class Level(models.IntegerChoices): MEMBER = 1, "member" ADMIN = 8, "administrator" - team: models.ForeignKey = models.ForeignKey( + team = models.ForeignKey( "posthog.Team", on_delete=models.CASCADE, related_name="explicit_memberships", related_query_name="explicit_membership", ) - parent_membership: models.ForeignKey = models.ForeignKey( + parent_membership = models.ForeignKey( "posthog.OrganizationMembership", on_delete=models.CASCADE, related_name="explicit_team_memberships", related_query_name="explicit_team_membership", ) - level: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField( - default=Level.MEMBER, choices=Level.choices - ) - joined_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) + level = models.PositiveSmallIntegerField(default=Level.MEMBER, choices=Level.choices) + joined_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) class Meta: constraints = [ diff --git a/ee/models/feature_flag_role_access.py b/ee/models/feature_flag_role_access.py index 003ede1b25e9e..867f2d562b944 100644 --- a/ee/models/feature_flag_role_access.py +++ b/ee/models/feature_flag_role_access.py @@ -2,20 +2,20 @@ class FeatureFlagRoleAccess(models.Model): - feature_flag: models.ForeignKey = models.ForeignKey( + feature_flag = models.ForeignKey( "posthog.FeatureFlag", on_delete=models.CASCADE, related_name="access", related_query_name="access", ) - role: models.ForeignKey = models.ForeignKey( + role = models.ForeignKey( "Role", on_delete=models.CASCADE, related_name="feature_flag_access", related_query_name="feature_flag_access", ) - added_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) + added_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) class Meta: constraints = [models.UniqueConstraint(fields=["role", "feature_flag"], name="unique_feature_flag_and_role")] diff --git a/ee/models/license.py b/ee/models/license.py index 283d9fd708760..5a18d8f8c585d 100644 --- a/ee/models/license.py +++ b/ee/models/license.py @@ -43,12 +43,12 @@ def first_valid(self) -> Optional["License"]: class License(models.Model): objects: LicenseManager = LicenseManager() - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - plan: models.CharField = models.CharField(max_length=200) - valid_until: models.DateTimeField = models.DateTimeField() - key: models.CharField = models.CharField(max_length=200) + created_at = models.DateTimeField(auto_now_add=True) + plan = models.CharField(max_length=200) + valid_until = models.DateTimeField() + key = models.CharField(max_length=200) # DEPRECATED: This is no longer used - max_users: models.IntegerField = models.IntegerField(default=None, null=True) # None = no restriction + max_users = models.IntegerField(default=None, null=True) # None = no restriction # NOTE: Remember to update the Billing Service as well. Long-term it will be the source of truth. SCALE_PLAN = "scale" diff --git a/ee/models/organization_resource_access.py b/ee/models/organization_resource_access.py index 201cb354177f1..924b3e9db2855 100644 --- a/ee/models/organization_resource_access.py +++ b/ee/models/organization_resource_access.py @@ -19,20 +19,16 @@ class Resources(models.TextChoices): INSIGHTS = "insights", "insights" DASHBOARDS = "dashboards", "dashboards" - resource: models.CharField = models.CharField(max_length=32, choices=Resources.choices) - access_level: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField( - default=AccessLevel.CAN_ALWAYS_EDIT, choices=AccessLevel.choices - ) - organization: models.ForeignKey = models.ForeignKey( - Organization, on_delete=models.CASCADE, related_name="resource_access" - ) - created_by: models.ForeignKey = models.ForeignKey( + resource = models.CharField(max_length=32, choices=Resources.choices) + access_level = models.PositiveSmallIntegerField(default=AccessLevel.CAN_ALWAYS_EDIT, choices=AccessLevel.choices) + organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name="resource_access") + created_by = models.ForeignKey( "posthog.User", on_delete=models.SET_NULL, null=True, ) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) class Meta: constraints = [ diff --git a/ee/models/property_definition.py b/ee/models/property_definition.py index a93b8e957511e..bb9b34fa406e1 100644 --- a/ee/models/property_definition.py +++ b/ee/models/property_definition.py @@ -5,12 +5,12 @@ class EnterprisePropertyDefinition(PropertyDefinition): - description: models.TextField = models.TextField(blank=True, null=True, default="") - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) + description = models.TextField(blank=True, null=True, default="") + updated_at = models.DateTimeField(auto_now=True) updated_by = models.ForeignKey("posthog.User", null=True, on_delete=models.SET_NULL, blank=True) - verified: models.BooleanField = models.BooleanField(default=False, blank=True) - verified_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) + verified = models.BooleanField(default=False, blank=True) + verified_at = models.DateTimeField(null=True, blank=True) verified_by = models.ForeignKey( "posthog.User", null=True, diff --git a/ee/models/role.py b/ee/models/role.py index 00880812b9d82..f37170818dbc3 100644 --- a/ee/models/role.py +++ b/ee/models/role.py @@ -5,19 +5,19 @@ class Role(UUIDModel): - name: models.CharField = models.CharField(max_length=200) - organization: models.ForeignKey = models.ForeignKey( + name = models.CharField(max_length=200) + organization = models.ForeignKey( "posthog.Organization", on_delete=models.CASCADE, related_name="roles", related_query_name="role", ) - feature_flags_access_level: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField( + feature_flags_access_level = models.PositiveSmallIntegerField( default=OrganizationResourceAccess.AccessLevel.CAN_ALWAYS_EDIT, choices=OrganizationResourceAccess.AccessLevel.choices, ) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - created_by: models.ForeignKey = models.ForeignKey( + created_at = models.DateTimeField(auto_now_add=True) + created_by = models.ForeignKey( "posthog.User", on_delete=models.SET_NULL, related_name="roles", @@ -30,29 +30,29 @@ class Meta: class RoleMembership(UUIDModel): - role: models.ForeignKey = models.ForeignKey( + role = models.ForeignKey( "Role", on_delete=models.CASCADE, related_name="roles", related_query_name="role", ) # TODO: Eventually remove this as we only need the organization membership - user: models.ForeignKey = models.ForeignKey( + user = models.ForeignKey( "posthog.User", on_delete=models.CASCADE, related_name="role_memberships", related_query_name="role_membership", ) - organization_member: models.ForeignKey = models.ForeignKey( + organization_member = models.ForeignKey( "posthog.OrganizationMembership", on_delete=models.CASCADE, related_name="role_memberships", related_query_name="role_membership", null=True, ) - joined_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) + joined_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) class Meta: constraints = [models.UniqueConstraint(fields=["role", "user"], name="unique_user_and_role")] diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 340ac998bcdad..7a560db891885 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -27,10 +27,32 @@ posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Un posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Unpacked dict entry 1 has incompatible type "dict[str, Any] | None"; expected "SupportsKeysAndGetItem[str, Any]" [dict-item] posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Unpacked dict entry 0 has incompatible type "dict[str, Any] | None"; expected "SupportsKeysAndGetItem[str, ResolveParamConfig | IncrementalParamConfig | Any]" [dict-item] posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Unpacked dict entry 1 has incompatible type "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None"; expected "SupportsKeysAndGetItem[str, ResolveParamConfig | IncrementalParamConfig | Any]" [dict-item] +posthog/utils.py:0: error: No overload variant of "asdict" matches argument type "type[DataclassInstance]" [call-overload] +posthog/utils.py:0: note: Possible overload variants: +posthog/utils.py:0: note: def asdict(obj: DataclassInstance) -> dict[str, Any] +posthog/utils.py:0: note: def [_T] asdict(obj: DataclassInstance, *, dict_factory: Callable[[list[tuple[str, Any]]], _T]) -> _T +posthog/utils.py:0: error: Name "timezone.datetime" is not defined [name-defined] +posthog/settings/data_stores.py:0: error: Incompatible types in assignment (expression has type "str | None", variable has type "str") [assignment] +posthog/settings/data_stores.py:0: error: Name "DATABASE_URL" already defined on line 0 [no-redef] +posthog/plugins/utils.py:0: error: Subclass of "str" and "bytes" cannot exist: would have incompatible method signatures [unreachable] +posthog/plugins/utils.py:0: error: Statement is unreachable [unreachable] +posthog/models/dashboard.py:0: error: Need type annotation for "insights" [var-annotated] posthog/hogql/database/schema/numbers.py:0: error: Incompatible types in assignment (expression has type "dict[str, IntegerDatabaseField]", variable has type "dict[str, FieldOrTable]") [assignment] posthog/hogql/database/schema/numbers.py:0: note: "Dict" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance posthog/hogql/database/schema/numbers.py:0: note: Consider using "Mapping" instead, which is covariant in the value type posthog/hogql/ast.py:0: error: Incompatible return value type (got "bool | None", expected "bool") [return-value] +posthog/warehouse/data_load/service.py:0: error: Unsupported operand types for >= ("timedelta" and "None") [operator] +posthog/warehouse/data_load/service.py:0: note: Left operand is of type "timedelta | None" +posthog/warehouse/data_load/service.py:0: error: Incompatible return value type (got "tuple[timedelta | None, timedelta]", expected "tuple[timedelta, timedelta]") [return-value] +posthog/warehouse/data_load/service.py:0: error: Unsupported operand types for >= ("timedelta" and "None") [operator] +posthog/warehouse/data_load/service.py:0: note: Left operand is of type "timedelta | None" +posthog/warehouse/data_load/service.py:0: error: Incompatible return value type (got "tuple[timedelta | None, timedelta]", expected "tuple[timedelta, timedelta]") [return-value] +posthog/warehouse/data_load/service.py:0: error: Incompatible return value type (got "tuple[timedelta | None, timedelta]", expected "tuple[timedelta, timedelta]") [return-value] +posthog/tasks/tasks.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] +posthog/models/subscription.py:0: error: Argument 2 to "SubscriptionResourceInfo" has incompatible type "str | None"; expected "str" [arg-type] +posthog/models/exported_asset.py:0: error: Value of type variable "_StrOrPromiseT" of "slugify" cannot be "str | None" [type-var] +posthog/models/action/action.py:0: error: Need type annotation for "events" [var-annotated] +posthog/models/action/action.py:0: error: Argument 1 to "len" has incompatible type "str | None"; expected "Sized" [arg-type] posthog/hogql/visitor.py:0: error: Incompatible types in assignment (expression has type "Expr", variable has type "CTE") [assignment] posthog/hogql/visitor.py:0: error: Incompatible types in assignment (expression has type "Expr", variable has type "CTE") [assignment] posthog/hogql/visitor.py:0: error: Incompatible types in assignment (expression has type "Expr", variable has type "CTE") [assignment] @@ -39,50 +61,35 @@ posthog/hogql/visitor.py:0: error: Incompatible types in assignment (expression posthog/hogql/visitor.py:0: error: Incompatible types in assignment (expression has type "WindowExpr", variable has type "CTE") [assignment] posthog/hogql/visitor.py:0: error: Incompatible types in assignment (expression has type "FieldAliasType", variable has type "BaseTableType | SelectUnionQueryType | SelectQueryType | SelectQueryAliasType | SelectViewType") [assignment] posthog/hogql/visitor.py:0: error: Incompatible types in assignment (expression has type "Type", variable has type "BaseTableType | SelectUnionQueryType | SelectQueryType | SelectQueryAliasType | SelectViewType") [assignment] +ee/models/license.py:0: error: Incompatible return value type (got "_T", expected "License | None") [return-value] +ee/models/license.py:0: error: Cannot use a covariant type variable as a parameter [misc] +ee/models/license.py:0: error: "_T" has no attribute "plan" [attr-defined] +ee/models/license.py:0: error: Incompatible return value type (got "str | bool", expected "bool") [return-value] +ee/models/explicit_team_membership.py:0: error: Incompatible return value type (got "int", expected "Level") [return-value] posthog/hogql/resolver_utils.py:0: error: Argument 1 to "lookup_field_by_name" has incompatible type "SelectQueryType | SelectUnionQueryType"; expected "SelectQueryType" [arg-type] +posthog/models/filters/mixins/simplify.py:0: error: Incompatible type for lookup 'pk': (got "str | int | list[str]", expected "str | int") [misc] posthog/hogql/parser.py:0: error: Item "None" of "list[Expr] | None" has no attribute "__iter__" (not iterable) [union-attr] posthog/hogql/parser.py:0: error: "None" has no attribute "text" [attr-defined] posthog/hogql/parser.py:0: error: "None" has no attribute "text" [attr-defined] posthog/hogql/parser.py:0: error: Statement is unreachable [unreachable] +posthog/helpers/dashboard_templates.py:0: error: Incompatible types in assignment (expression has type "str | None", variable has type "str | Combinable") [assignment] +posthog/hogql/functions/cohort.py:0: error: Incompatible type for lookup 'team_id': (got "int | None", expected "str | int") [misc] +posthog/hogql/functions/cohort.py:0: error: Incompatible type for lookup 'team_id': (got "int | None", expected "str | int") [misc] +posthog/hogql/database/schema/persons_pdi.py:0: error: Incompatible types in assignment (expression has type "Organization | None", variable has type "Organization") [assignment] posthog/hogql/database/schema/groups.py:0: error: Incompatible types in assignment (expression has type "dict[str, DatabaseField]", variable has type "dict[str, FieldOrTable]") [assignment] posthog/hogql/database/schema/groups.py:0: note: "Dict" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance posthog/hogql/database/schema/groups.py:0: note: Consider using "Mapping" instead, which is covariant in the value type posthog/hogql/database/schema/groups.py:0: error: Incompatible types in assignment (expression has type "dict[str, DatabaseField]", variable has type "dict[str, FieldOrTable]") [assignment] posthog/hogql/database/schema/groups.py:0: note: "Dict" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance posthog/hogql/database/schema/groups.py:0: note: Consider using "Mapping" instead, which is covariant in the value type -posthog/storage/object_storage.py:0: error: Import cycle from Django settings module prevents type inference for 'OBJECT_STORAGE_ENABLED' [misc] -posthog/storage/object_storage.py:0: error: Import cycle from Django settings module prevents type inference for 'OBJECT_STORAGE_ENDPOINT' [misc] -posthog/storage/object_storage.py:0: error: Import cycle from Django settings module prevents type inference for 'OBJECT_STORAGE_REGION' [misc] -posthog/storage/object_storage.py:0: error: Import cycle from Django settings module prevents type inference for 'OBJECT_STORAGE_BUCKET' [misc] -posthog/storage/object_storage.py:0: error: Import cycle from Django settings module prevents type inference for 'OBJECT_STORAGE_BUCKET' [misc] -posthog/storage/object_storage.py:0: error: Import cycle from Django settings module prevents type inference for 'OBJECT_STORAGE_BUCKET' [misc] -posthog/storage/object_storage.py:0: error: Import cycle from Django settings module prevents type inference for 'OBJECT_STORAGE_BUCKET' [misc] -posthog/storage/object_storage.py:0: error: Import cycle from Django settings module prevents type inference for 'OBJECT_STORAGE_BUCKET' [misc] -posthog/storage/object_storage.py:0: error: Import cycle from Django settings module prevents type inference for 'OBJECT_STORAGE_BUCKET' [misc] -posthog/storage/object_storage.py:0: error: Import cycle from Django settings module prevents type inference for 'OBJECT_STORAGE_BUCKET' [misc] -posthog/storage/object_storage.py:0: error: Import cycle from Django settings module prevents type inference for 'OBJECT_STORAGE_BUCKET' [misc] -posthog/redis.py:0: error: Import cycle from Django settings module prevents type inference for 'REDIS_URL' [misc] -posthog/plugins/utils.py:0: error: Subclass of "str" and "bytes" cannot exist: would have incompatible method signatures [unreachable] -posthog/plugins/utils.py:0: error: Statement is unreachable [unreachable] -posthog/clickhouse/kafka_engine.py:0: error: Import cycle from Django settings module prevents type inference for 'KAFKA_HOSTS_FOR_CLICKHOUSE' [misc] -posthog/utils.py:0: error: Import cycle from Django settings module prevents type inference for 'PERSISTED_FEATURE_FLAGS' [misc] -posthog/utils.py:0: error: Import cycle from Django settings module prevents type inference for 'OBJECT_STORAGE_ENABLED' [misc] -posthog/utils.py:0: error: No overload variant of "asdict" matches argument type "type[DataclassInstance]" [call-overload] -posthog/utils.py:0: note: Possible overload variants: -posthog/utils.py:0: note: def asdict(obj: DataclassInstance) -> dict[str, Any] -posthog/utils.py:0: note: def [_T] asdict(obj: DataclassInstance, *, dict_factory: Callable[[list[tuple[str, Any]]], _T]) -> _T -posthog/utils.py:0: error: Name "timezone.datetime" is not defined [name-defined] -posthog/utils.py:0: error: Import cycle from Django settings module prevents type inference for 'DECIDE_TRACK_TEAM_IDS' [misc] -posthog/models/dashboard.py:0: error: Need type annotation for "insights" [var-annotated] -posthog/tasks/tasks.py:0: error: Import cycle from Django settings module prevents type inference for 'INGESTION_LAG_METRIC_TEAM_IDS' [misc] -posthog/tasks/tasks.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] -posthog/warehouse/s3.py:0: error: Import cycle from Django settings module prevents type inference for 'OBJECT_STORAGE_ENDPOINT' [misc] -posthog/settings/data_stores.py:0: error: Incompatible types in assignment (expression has type "str | None", variable has type "str") [assignment] -posthog/settings/data_stores.py:0: error: Name "DATABASE_URL" already defined on line 0 [no-redef] -posthog/models/filters/mixins/simplify.py:0: error: Incompatible type for lookup 'pk': (got "str | int | list[str]", expected "str | int") [misc] +posthog/hogql/database/schema/persons.py:0: error: Incompatible types in assignment (expression has type "Organization | None", variable has type "Organization") [assignment] +posthog/batch_exports/service.py:0: error: Argument 4 to "backfill_export" has incompatible type "datetime | None"; expected "datetime" [arg-type] posthog/models/filters/base_filter.py:0: error: "HogQLContext" has no attribute "person_on_events_mode" [attr-defined] posthog/models/team/team.py:0: error: Statement is unreachable [unreachable] posthog/models/team/team.py:0: error: Statement is unreachable [unreachable] +posthog/models/hog_functions/hog_function.py:0: error: Argument 1 to "get" of "dict" has incompatible type "str | None"; expected "str" [arg-type] +posthog/models/hog_functions/hog_function.py:0: error: Argument 2 to "get_hog_function_status" has incompatible type "UUID"; expected "str" [arg-type] +posthog/models/hog_functions/hog_function.py:0: error: Argument 2 to "patch_hog_function_status" has incompatible type "UUID"; expected "str" [arg-type] posthog/models/user.py:0: error: Incompatible types in assignment (expression has type "type[User]", base class "BaseManager" defined the type as "type[_T]") [assignment] posthog/models/user.py:0: error: Cannot override class variable (previously declared on base class "AbstractBaseUser") with instance variable [misc] posthog/models/user.py:0: error: Incompatible types in assignment (expression has type "None", base class "AbstractUser" defined the type as "CharField[str | int | Combinable, str]") [assignment] @@ -96,30 +103,13 @@ posthog/models/user.py:0: note: Subclass: posthog/models/user.py:0: note: bool posthog/models/user.py:0: error: "User" has no attribute "social_auth" [attr-defined] posthog/models/user.py:0: error: "User" has no attribute "social_auth" [attr-defined] +posthog/models/plugin.py:0: error: Argument 1 to "extract_plugin_code" has incompatible type "bytes | memoryview | None"; expected "bytes" [arg-type] posthog/models/plugin.py:0: error: Name "timezone.datetime" is not defined [name-defined] posthog/models/plugin.py:0: error: Name "timezone.datetime" is not defined [name-defined] posthog/models/person/person.py:0: error: "_T" has no attribute "_add_distinct_ids" [attr-defined] -posthog/models/person/person.py:0: error: Incompatible types in assignment (expression has type "list[Never]", variable has type "_QuerySet[PersonDistinctId, str]") [assignment] -posthog/hogql/database/database.py:0: error: "FieldOrTable" has no attribute "fields" [attr-defined] -posthog/warehouse/models/datawarehouse_saved_query.py:0: error: Argument 1 to "create_hogql_database" has incompatible type "int | None"; expected "int" [arg-type] -posthog/warehouse/models/datawarehouse_saved_query.py:0: error: Incompatible types in assignment (expression has type "Expr", variable has type "SelectQuery | SelectUnionQuery") [assignment] -posthog/models/feature_flag/flag_matching.py:0: error: Statement is unreachable [unreachable] -posthog/models/feature_flag/flag_matching.py:0: error: Value of type variable "_E" of "ExpressionWrapper" cannot be "object" [type-var] -posthog/models/feature_flag/flag_matching.py:0: error: Value of type variable "_E" of "ExpressionWrapper" cannot be "object" [type-var] -posthog/models/feature_flag/flag_matching.py:0: error: Argument 1 to "get" of "dict" has incompatible type "str | None"; expected "str" [arg-type] -posthog/models/feature_flag/flag_matching.py:0: error: Value of type variable "_E" of "ExpressionWrapper" cannot be "object" [type-var] -ee/models/license.py:0: error: Incompatible return value type (got "_T", expected "License | None") [return-value] -ee/models/license.py:0: error: Cannot use a covariant type variable as a parameter [misc] -ee/models/license.py:0: error: "_T" has no attribute "plan" [attr-defined] -posthog/hogql_queries/utils/query_date_range.py:0: error: Item "None" of "dict[str, int] | None" has no attribute "get" [union-attr] -posthog/hogql_queries/utils/query_date_range.py:0: error: Unsupported operand types for * ("object" and "int") [operator] -posthog/hogql_queries/utils/query_date_range.py:0: error: Incompatible return value type (got "int", expected "timedelta") [return-value] -posthog/hogql_queries/utils/query_date_range.py:0: error: Item "None" of "IntervalType | None" has no attribute "name" [union-attr] -posthog/hogql_queries/utils/query_date_range.py:0: error: Item "None" of "IntervalType | None" has no attribute "name" [union-attr] -posthog/hogql_queries/utils/query_date_range.py:0: error: Incompatible default for argument "source" (default has type "None", argument has type "Expr") [assignment] -posthog/hogql_queries/utils/query_date_range.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -posthog/hogql_queries/utils/query_date_range.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -posthog/hogql_queries/utils/query_date_range.py:0: error: Item "None" of "IntervalType | None" has no attribute "name" [union-attr] +posthog/models/person/person.py:0: error: Argument "version" to "create_person" has incompatible type "int | None"; expected "int" [arg-type] +posthog/models/person/person.py:0: error: Incompatible types in assignment (expression has type "list[Never]", variable has type "QuerySet[PersonDistinctId, str]") [assignment] +posthog/models/organization_invite.py:0: error: Argument "level" to "join" of "User" has incompatible type "int"; expected "Level" [arg-type] posthog/hogql_queries/legacy_compatibility/filter_to_query.py:0: error: Dict entry 4 has incompatible type "str": "Literal[0, 1, 2, 3, 4] | None"; expected "str": "str | None" [dict-item] posthog/hogql_queries/legacy_compatibility/filter_to_query.py:0: error: Item "None" of "Any | None" has no attribute "__iter__" (not iterable) [union-attr] posthog/hogql_queries/legacy_compatibility/filter_to_query.py:0: error: Argument 1 to "float" has incompatible type "Any | None"; expected "str | Buffer | SupportsFloat | SupportsIndex" [arg-type] @@ -131,31 +121,26 @@ posthog/hogql_queries/legacy_compatibility/filter_to_query.py:0: error: Argument posthog/hogql_queries/legacy_compatibility/filter_to_query.py:0: error: Dict entry 0 has incompatible type "str": "PathsFilter"; expected "str": "TrendsFilter" [dict-item] posthog/hogql_queries/legacy_compatibility/filter_to_query.py:0: error: Dict entry 0 has incompatible type "str": "LifecycleFilter"; expected "str": "TrendsFilter" [dict-item] posthog/hogql_queries/legacy_compatibility/filter_to_query.py:0: error: Dict entry 0 has incompatible type "str": "StickinessFilter"; expected "str": "TrendsFilter" [dict-item] -posthog/hogql/functions/cohort.py:0: error: Incompatible type for lookup 'team_id': (got "int | None", expected "str | int") [misc] -posthog/hogql/functions/cohort.py:0: error: Incompatible type for lookup 'team_id': (got "int | None", expected "str | int") [misc] -posthog/demo/matrix/matrix.py:0: error: Name "timezone.datetime" is not defined [name-defined] -posthog/demo/matrix/matrix.py:0: error: Name "timezone.datetime" is not defined [name-defined] -posthog/demo/matrix/matrix.py:0: error: Name "timezone.datetime" is not defined [name-defined] -posthog/api/utils.py:0: error: Incompatible types in assignment (expression has type "type[EventDefinition]", variable has type "type[EnterpriseEventDefinition]") [assignment] -posthog/api/utils.py:0: error: Argument 1 to "UUID" has incompatible type "int | str"; expected "str | None" [arg-type] -ee/billing/quota_limiting.py:0: error: Unsupported target for indexed assignment ("object") [index] -ee/billing/quota_limiting.py:0: error: "object" has no attribute "get" [attr-defined] -ee/billing/quota_limiting.py:0: error: Unsupported target for indexed assignment ("object") [index] -ee/billing/quota_limiting.py:0: error: Unsupported target for indexed assignment ("object") [index] -posthog/tasks/email.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] -posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: List item 1 has incompatible type "str | None"; expected "str" [list-item] -posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Argument "chain" to "Field" has incompatible type "list[str]"; expected "list[str | int]" [arg-type] -posthog/hogql_queries/insights/trends/aggregation_operations.py:0: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance -posthog/hogql_queries/insights/trends/aggregation_operations.py:0: note: Consider using "Sequence" instead, which is covariant -posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: List item 1 has incompatible type "str | None"; expected "str" [list-item] -posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Argument "chain" to "Field" has incompatible type "list[str | int] | list[str]"; expected "list[str | int]" [arg-type] -posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Item "SelectUnionQuery" of "SelectQuery | SelectUnionQuery" has no attribute "select" [union-attr] -posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Item "SelectUnionQuery" of "SelectQuery | SelectUnionQuery" has no attribute "select" [union-attr] -posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Item "SelectUnionQuery" of "SelectQuery | SelectUnionQuery" has no attribute "group_by" [union-attr] -posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Item "None" of "list[Expr] | None" has no attribute "append" [union-attr] -posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Item "SelectUnionQuery" of "SelectQuery | SelectUnionQuery" has no attribute "select" [union-attr] -posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Item "SelectUnionQuery" of "SelectQuery | SelectUnionQuery" has no attribute "group_by" [union-attr] -posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Item "None" of "list[Expr] | Any | None" has no attribute "append" [union-attr] +posthog/session_recordings/models/session_recording.py:0: error: Argument "distinct_id" to "MissingPerson" has incompatible type "str | None"; expected "str" [arg-type] +posthog/session_recordings/models/session_recording.py:0: error: Incompatible type for lookup 'persondistinctid__team_id': (got "Team", expected "str | int") [misc] +ee/tasks/subscriptions/slack_subscriptions.py:0: error: Item "None" of "datetime | None" has no attribute "strftime" [union-attr] +posthog/warehouse/models/table.py:0: error: Item "None" of "DataWarehouseCredential | None" has no attribute "access_key" [union-attr] +posthog/warehouse/models/table.py:0: error: Item "None" of "DataWarehouseCredential | None" has no attribute "access_secret" [union-attr] +posthog/warehouse/models/table.py:0: error: Item "None" of "DataWarehouseCredential | None" has no attribute "access_key" [union-attr] +posthog/warehouse/models/table.py:0: error: Item "None" of "DataWarehouseCredential | None" has no attribute "access_secret" [union-attr] +posthog/warehouse/models/table.py:0: error: Item "None" of "DataWarehouseCredential | None" has no attribute "access_key" [union-attr] +posthog/warehouse/models/table.py:0: error: Item "None" of "DataWarehouseCredential | None" has no attribute "access_secret" [union-attr] +posthog/queries/util.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/models/cohort/cohort.py:0: error: Need type annotation for "people" [var-annotated] +posthog/hogql_queries/utils/query_date_range.py:0: error: Item "None" of "dict[str, int] | None" has no attribute "get" [union-attr] +posthog/hogql_queries/utils/query_date_range.py:0: error: Unsupported operand types for * ("object" and "int") [operator] +posthog/hogql_queries/utils/query_date_range.py:0: error: Incompatible return value type (got "int", expected "timedelta") [return-value] +posthog/hogql_queries/utils/query_date_range.py:0: error: Item "None" of "IntervalType | None" has no attribute "name" [union-attr] +posthog/hogql_queries/utils/query_date_range.py:0: error: Item "None" of "IntervalType | None" has no attribute "name" [union-attr] +posthog/hogql_queries/utils/query_date_range.py:0: error: Incompatible default for argument "source" (default has type "None", argument has type "Expr") [assignment] +posthog/hogql_queries/utils/query_date_range.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +posthog/hogql_queries/utils/query_date_range.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +posthog/hogql_queries/utils/query_date_range.py:0: error: Item "None" of "IntervalType | None" has no attribute "name" [union-attr] posthog/hogql/resolver.py:0: error: Argument 1 of "visit" is incompatible with supertype "Visitor"; supertype defines the argument type as "AST | None" [override] posthog/hogql/resolver.py:0: note: This violates the Liskov substitution principle posthog/hogql/resolver.py:0: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides @@ -191,7 +176,23 @@ posthog/hogql/resolver.py:0: error: Statement is unreachable [unreachable] posthog/hogql/resolver.py:0: error: Item "None" of "Type | None" has no attribute "resolve_constant_type" [union-attr] posthog/hogql/resolver.py:0: error: Item "None" of "Type | None" has no attribute "resolve_constant_type" [union-attr] posthog/hogql/resolver.py:0: error: Item "None" of "Type | None" has no attribute "resolve_constant_type" [union-attr] -posthog/demo/matrix/taxonomy_inference.py:0: error: Name "timezone.datetime" is not defined [name-defined] +posthog/models/feature_flag/feature_flag.py:0: error: Need type annotation for "analytics_dashboards" [var-annotated] +posthog/models/feature_flag/feature_flag.py:0: error: Unsupported right operand type for in ("str | Any | None") [operator] +posthog/models/feature_flag/feature_flag.py:0: error: Item "None" of "Insight | None" has no attribute "name" [union-attr] +posthog/models/feature_flag/feature_flag.py:0: error: Incompatible types in assignment (expression has type "User | None", variable has type "User | AnonymousUser") [assignment] +posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: List item 1 has incompatible type "str | None"; expected "str" [list-item] +posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Argument "chain" to "Field" has incompatible type "list[str]"; expected "list[str | int]" [arg-type] +posthog/hogql_queries/insights/trends/aggregation_operations.py:0: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance +posthog/hogql_queries/insights/trends/aggregation_operations.py:0: note: Consider using "Sequence" instead, which is covariant +posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: List item 1 has incompatible type "str | None"; expected "str" [list-item] +posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Argument "chain" to "Field" has incompatible type "list[str | int] | list[str]"; expected "list[str | int]" [arg-type] +posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Item "SelectUnionQuery" of "SelectQuery | SelectUnionQuery" has no attribute "select" [union-attr] +posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Item "SelectUnionQuery" of "SelectQuery | SelectUnionQuery" has no attribute "select" [union-attr] +posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Item "SelectUnionQuery" of "SelectQuery | SelectUnionQuery" has no attribute "group_by" [union-attr] +posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Item "None" of "list[Expr] | None" has no attribute "append" [union-attr] +posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Item "SelectUnionQuery" of "SelectQuery | SelectUnionQuery" has no attribute "select" [union-attr] +posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Item "SelectUnionQuery" of "SelectQuery | SelectUnionQuery" has no attribute "group_by" [union-attr] +posthog/hogql_queries/insights/trends/aggregation_operations.py:0: error: Item "None" of "list[Expr] | Any | None" has no attribute "append" [union-attr] posthog/hogql/transforms/lazy_tables.py:0: error: Incompatible types in assignment (expression has type "dict[Never, Never]", variable has type "list[ConstraintOverride]") [assignment] posthog/hogql/transforms/lazy_tables.py:0: error: Non-overlapping equality check (left operand type: "TableType", right operand type: "LazyTableType") [comparison-overlap] posthog/hogql/transforms/lazy_tables.py:0: error: Non-overlapping equality check (left operand type: "TableType", right operand type: "LazyTableType") [comparison-overlap] @@ -218,6 +219,20 @@ posthog/hogql/transforms/in_cohort.py:0: error: Item "None" of "JoinConstraint | posthog/hogql/transforms/in_cohort.py:0: error: Item "Expr" of "Expr | Any" has no attribute "right" [union-attr] posthog/hogql/transforms/in_cohort.py:0: error: List item 0 has incompatible type "SelectQueryType | None"; expected "SelectQueryType" [list-item] posthog/hogql/transforms/in_cohort.py:0: error: List item 0 has incompatible type "SelectQueryType | None"; expected "SelectQueryType" [list-item] +posthog/hogql/database/database.py:0: error: Argument "week_start_day" to "Database" has incompatible type "int | Any | None"; expected "WeekStartDay | None" [arg-type] +posthog/hogql/database/database.py:0: error: "FieldOrTable" has no attribute "fields" [attr-defined] +posthog/warehouse/models/datawarehouse_saved_query.py:0: error: Argument 1 to "create_hogql_database" has incompatible type "int | None"; expected "int" [arg-type] +posthog/warehouse/models/datawarehouse_saved_query.py:0: error: Incompatible types in assignment (expression has type "Expr", variable has type "SelectQuery | SelectUnionQuery") [assignment] +posthog/models/feature_flag/flag_matching.py:0: error: Statement is unreachable [unreachable] +posthog/models/feature_flag/flag_matching.py:0: error: Value expression in dictionary comprehension has incompatible type "int"; expected type "Literal[0, 1, 2, 3, 4]" [misc] +posthog/models/feature_flag/flag_matching.py:0: error: Value of type variable "_E" of "ExpressionWrapper" cannot be "object" [type-var] +posthog/models/feature_flag/flag_matching.py:0: error: Value of type variable "_E" of "ExpressionWrapper" cannot be "object" [type-var] +posthog/models/feature_flag/flag_matching.py:0: error: Argument 1 to "get" of "dict" has incompatible type "str | None"; expected "str" [arg-type] +posthog/models/feature_flag/flag_matching.py:0: error: Value of type variable "_E" of "ExpressionWrapper" cannot be "object" [type-var] +posthog/models/activity_logging/activity_log.py:0: error: Name "limit" is not defined [name-defined] +posthog/models/activity_logging/activity_log.py:0: error: Name "limit" is not defined [name-defined] +posthog/models/activity_logging/activity_log.py:0: error: Too many arguments for "get_activity_page" [call-arg] +posthog/models/activity_logging/activity_log.py:0: error: Too many arguments for "get_activity_page" [call-arg] posthog/hogql/printer.py:0: error: Argument 1 to "create_hogql_database" has incompatible type "int | None"; expected "int" [arg-type] posthog/hogql/printer.py:0: error: List comprehension has incompatible type List[SelectQueryType | None]; expected List[SelectQueryType] [misc] posthog/hogql/printer.py:0: error: Argument "stack" to "_Printer" has incompatible type "list[SelectQuery]"; expected "list[AST] | None" [arg-type] @@ -237,12 +252,44 @@ posthog/hogql/printer.py:0: error: "FieldOrTable" has no attribute "name" [attr posthog/hogql/printer.py:0: error: "FieldOrTable" has no attribute "name" [attr-defined] posthog/hogql/printer.py:0: error: Argument 2 to "_get_materialized_column" of "_Printer" has incompatible type "str | int"; expected "str" [arg-type] posthog/hogql/printer.py:0: error: Argument 1 to "_print_identifier" of "_Printer" has incompatible type "str | None"; expected "str" [arg-type] -posthog/api/documentation.py:0: error: Signature of "run_validation" incompatible with supertype "Field" [override] -posthog/api/documentation.py:0: note: Superclass: -posthog/api/documentation.py:0: note: def run_validation(self, data: Any = ...) -> Any -posthog/api/documentation.py:0: note: Subclass: -posthog/api/documentation.py:0: note: def run_validation(self, data: Any) -> Any -posthog/api/action.py:0: error: Argument 1 to has incompatible type "*tuple[str, ...]"; expected "type[BaseRenderer]" [arg-type] +posthog/user_permissions.py:0: error: Key expression in dictionary comprehension has incompatible type "UUID"; expected type "int" [misc] +posthog/user_permissions.py:0: error: Incompatible return value type (got "int", expected "Level | None") [return-value] +posthog/user_permissions.py:0: error: Incompatible return value type (got "int", expected "Level | None") [return-value] +posthog/user_permissions.py:0: error: Incompatible return value type (got "int", expected "RestrictionLevel") [return-value] +posthog/tasks/warehouse.py:0: error: Argument 1 to "cancel_external_data_workflow" has incompatible type "str | None"; expected "str" [arg-type] +posthog/tasks/update_survey_iteration.py:0: error: Incompatible types in assignment (expression has type "ForeignKey[Any, _ST] | Any", variable has type "FeatureFlag | Combinable | None") [assignment] +posthog/tasks/update_survey_iteration.py:0: error: Item "None" of "FeatureFlag | None" has no attribute "filters" [union-attr] +posthog/tasks/update_survey_iteration.py:0: error: Item "None" of "FeatureFlag | None" has no attribute "filters" [union-attr] +posthog/tasks/update_survey_iteration.py:0: error: Item "None" of "FeatureFlag | None" has no attribute "save" [union-attr] +posthog/tasks/update_survey_iteration.py:0: error: Incompatible type for "key" of "FeatureFlag" (got "UUID", expected "str | int | Combinable") [misc] +posthog/permissions.py:0: error: Argument 2 to "feature_enabled" has incompatible type "str | None"; expected "str" [arg-type] +posthog/models/event/util.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "datetime") [assignment] +posthog/models/event/util.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/event_usage.py:0: error: Argument 1 to "capture" has incompatible type "str | None"; expected "str" [arg-type] +posthog/event_usage.py:0: error: Argument 1 to "capture" has incompatible type "str | None"; expected "str" [arg-type] +posthog/event_usage.py:0: error: Argument 1 to "alias" has incompatible type "str | None"; expected "str" [arg-type] +posthog/event_usage.py:0: error: Argument 1 to "capture" has incompatible type "str | None"; expected "str" [arg-type] +posthog/event_usage.py:0: error: Argument 1 to "capture" has incompatible type "str | None"; expected "str" [arg-type] +posthog/event_usage.py:0: error: Argument 1 to "capture" has incompatible type "str | None"; expected "str" [arg-type] +posthog/event_usage.py:0: error: Argument 1 to "capture" has incompatible type "str | None"; expected "str" [arg-type] +posthog/event_usage.py:0: error: Argument 1 to "capture" has incompatible type "str | None"; expected "str" [arg-type] +posthog/event_usage.py:0: error: Argument 1 to "capture" has incompatible type "str | None"; expected "str" [arg-type] +posthog/event_usage.py:0: error: Argument 1 to "capture" has incompatible type "str | None"; expected "str" [arg-type] +posthog/event_usage.py:0: error: Argument 1 to "capture" has incompatible type "str | None"; expected "str" [arg-type] +posthog/event_usage.py:0: error: Argument 1 to "capture" has incompatible type "str | None"; expected "str" [arg-type] +posthog/demo/matrix/taxonomy_inference.py:0: error: Name "timezone.datetime" is not defined [name-defined] +posthog/demo/matrix/matrix.py:0: error: Name "timezone.datetime" is not defined [name-defined] +posthog/demo/matrix/matrix.py:0: error: Name "timezone.datetime" is not defined [name-defined] +posthog/demo/matrix/matrix.py:0: error: Name "timezone.datetime" is not defined [name-defined] +posthog/api/utils.py:0: error: Incompatible types in assignment (expression has type "type[EventDefinition]", variable has type "type[EnterpriseEventDefinition]") [assignment] +posthog/api/utils.py:0: error: Argument 1 to "UUID" has incompatible type "int | str"; expected "str | None" [arg-type] +posthog/api/shared.py:0: error: Incompatible return value type (got "int | None", expected "Level | None") [return-value] +ee/billing/quota_limiting.py:0: error: Argument 2 to "feature_enabled" has incompatible type "UUID"; expected "str" [arg-type] +ee/billing/quota_limiting.py:0: error: List comprehension has incompatible type List[int]; expected List[str] [misc] +ee/billing/quota_limiting.py:0: error: Unsupported target for indexed assignment ("object") [index] +ee/billing/quota_limiting.py:0: error: "object" has no attribute "get" [attr-defined] +ee/billing/quota_limiting.py:0: error: Unsupported target for indexed assignment ("object") [index] +ee/billing/quota_limiting.py:0: error: Unsupported target for indexed assignment ("object") [index] posthog/test/base.py:0: error: Module has no attribute "configure" [attr-defined] posthog/test/base.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Organization") [assignment] posthog/test/base.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Project") [assignment] @@ -258,15 +305,38 @@ posthog/test/base.py:0: error: Item "None" of "FrameType | None" has no attribut posthog/test/base.py:0: error: Item "None" of "FrameType | Any | None" has no attribute "f_locals" [union-attr] posthog/test/base.py:0: error: Item "None" of "FrameType | None" has no attribute "f_back" [union-attr] posthog/test/base.py:0: error: Item "None" of "FrameType | Any | None" has no attribute "f_locals" [union-attr] +posthog/tasks/email.py:0: error: Item "None" of "User | None" has no attribute "first_name" [union-attr] +posthog/tasks/email.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] +posthog/tasks/email.py:0: error: Argument "email" to "add_recipient" of "EmailMessage" has incompatible type "str | None"; expected "str" [arg-type] +posthog/tasks/email.py:0: error: Argument 1 to "capture" has incompatible type "str | None"; expected "str" [arg-type] +posthog/tasks/email.py:0: error: Incompatible types in assignment (expression has type "Team | None", variable has type "Team") [assignment] +posthog/api/routing.py:0: error: Incompatible return value type (got "Project | None", expected "Project") [return-value] +posthog/api/documentation.py:0: error: Signature of "run_validation" incompatible with supertype "Field" [override] +posthog/api/documentation.py:0: note: Superclass: +posthog/api/documentation.py:0: note: def run_validation(self, data: Any = ...) -> Any +posthog/api/documentation.py:0: note: Subclass: +posthog/api/documentation.py:0: note: def run_validation(self, data: Any) -> Any +ee/tasks/subscriptions/email_subscriptions.py:0: error: Item "None" of "User | None" has no attribute "email" [union-attr] +ee/tasks/subscriptions/email_subscriptions.py:0: error: Item "None" of "datetime | None" has no attribute "isoformat" [union-attr] +ee/tasks/subscriptions/email_subscriptions.py:0: error: Item "None" of "datetime | None" has no attribute "strftime" [union-attr] +ee/tasks/subscriptions/email_subscriptions.py:0: error: Item "None" of "User | None" has no attribute "first_name" [union-attr] +ee/billing/billing_manager.py:0: error: Module has no attribute "utc" [attr-defined] +ee/billing/billing_manager.py:0: error: Cannot resolve keyword 'distinct_id' into field. Choices are: explicit_team_membership, id, joined_at, level, organization, organization_id, role_membership, updated_at, user, user_id [misc] +ee/billing/billing_manager.py:0: error: Cannot resolve keyword 'email' into field. Choices are: explicit_team_membership, id, joined_at, level, organization, organization_id, role_membership, updated_at, user, user_id [misc] +ee/billing/billing_manager.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "bool | Combinable | None") [assignment] posthog/models/property/util.py:0: error: Incompatible type for lookup 'pk': (got "str | int | list[str]", expected "str | int") [misc] posthog/models/property/util.py:0: error: Argument 3 to "format_filter_query" has incompatible type "HogQLContext | None"; expected "HogQLContext" [arg-type] posthog/models/property/util.py:0: error: Argument 3 to "format_cohort_subquery" has incompatible type "HogQLContext | None"; expected "HogQLContext" [arg-type] posthog/models/property/util.py:0: error: Argument 1 to "append" of "list" has incompatible type "str | int"; expected "str" [arg-type] posthog/models/property/util.py:0: error: Argument 1 to "append" of "list" has incompatible type "str | int"; expected "str" [arg-type] posthog/models/property/util.py:0: error: Argument 1 to "append" of "list" has incompatible type "str | int"; expected "str" [arg-type] +posthog/api/organization.py:0: error: Incompatible return value type (got "int | None", expected "Level | None") [return-value] +posthog/api/email_verification.py:0: error: Argument 2 to "feature_enabled" has incompatible type "UUID"; expected "str" [arg-type] +posthog/api/capture.py:0: error: Module has no attribute "utc" [attr-defined] posthog/queries/trends/util.py:0: error: Argument 1 to "translate_hogql" has incompatible type "str | None"; expected "str" [arg-type] posthog/hogql/property.py:0: error: Incompatible type for lookup 'id': (got "str | int | list[str]", expected "str | int") [misc] posthog/hogql/property.py:0: error: Incompatible type for lookup 'pk': (got "str | float", expected "str | int") [misc] +posthog/api/action.py:0: error: Argument 1 to has incompatible type "*tuple[str, ...]"; expected "type[BaseRenderer]" [arg-type] posthog/hogql/filters.py:0: error: Incompatible default for argument "team" (default has type "None", argument has type "Team") [assignment] posthog/hogql/filters.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True posthog/hogql/filters.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase @@ -283,9 +353,17 @@ posthog/hogql_queries/hogql_query_runner.py:0: error: Incompatible return value posthog/hogql_queries/events_query_runner.py:0: error: Statement is unreachable [unreachable] posthog/queries/breakdown_props.py:0: error: Argument 1 to "translate_hogql" has incompatible type "str | int"; expected "str" [arg-type] posthog/queries/breakdown_props.py:0: error: Incompatible type for lookup 'pk': (got "str | None", expected "str | int") [misc] +posthog/queries/breakdown_props.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] +posthog/queries/actor_base_query.py:0: error: Incompatible types (expression has type "datetime", TypedDict item "created_at" has type "str | None") [typeddict-item] +posthog/queries/actor_base_query.py:0: error: Incompatible types (expression has type "datetime", TypedDict item "created_at" has type "str | None") [typeddict-item] posthog/hogql_queries/insights/funnels/base.py:0: error: Incompatible type for lookup 'pk': (got "str | int | None", expected "str | int") [misc] posthog/queries/foss_cohort_query.py:0: error: Incompatible type for lookup 'pk': (got "str | int | list[str]", expected "str | int") [misc] posthog/queries/funnels/base.py:0: error: "HogQLContext" has no attribute "person_on_events_mode" [attr-defined] +posthog/queries/funnels/base.py:0: error: Incompatible types in assignment (expression has type "int | str | None", variable has type "str | None") [assignment] +posthog/queries/funnels/base.py:0: error: Unsupported right operand type for in ("object") [operator] +posthog/queries/funnels/base.py:0: error: "object" has no attribute "append" [attr-defined] +posthog/queries/funnels/base.py:0: error: Unsupported right operand type for in ("object") [operator] +posthog/queries/funnels/base.py:0: error: "object" has no attribute "append" [attr-defined] posthog/queries/funnels/base.py:0: error: Argument 1 to "translate_hogql" has incompatible type "str | int"; expected "str" [arg-type] posthog/queries/trends/trends_actors.py:0: error: Incompatible type for lookup 'pk': (got "str | None", expected "str | int") [misc] posthog/queries/paths/paths_actors.py:0: error: Incompatible types in assignment (expression has type "str", target has type "int | list[str] | None") [assignment] @@ -293,17 +371,29 @@ posthog/queries/paths/paths_actors.py:0: error: Incompatible types in assignment posthog/queries/paths/paths_actors.py:0: error: Incompatible types in assignment (expression has type "str", target has type "int | list[str] | None") [assignment] ee/clickhouse/queries/funnels/funnel_correlation.py:0: error: Statement is unreachable [unreachable] posthog/api/insight.py:0: error: Argument 1 to has incompatible type "*tuple[str, ...]"; expected "type[BaseRenderer]" [arg-type] -posthog/api/dashboards/dashboard.py:0: error: Argument 1 to "dashboard_queryset" of "DashboardTile" has incompatible type "DashboardTile_RelatedManager"; expected "_QuerySet[Any, Any]" [arg-type] +posthog/api/dashboards/dashboard.py:0: error: Argument 1 to "dashboard_queryset" of "DashboardTile" has incompatible type "DashboardTile_RelatedManager"; expected "QuerySet[Any, Any]" [arg-type] posthog/api/person.py:0: error: Argument 1 to has incompatible type "*tuple[str, ...]"; expected "type[BaseRenderer]" [arg-type] +posthog/api/person.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/person.py:0: error: Argument 1 to "loads" has incompatible type "str | None"; expected "str | bytes | bytearray" [arg-type] +posthog/api/person.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/person.py:0: error: Argument "user" to "log_activity" has incompatible type "User | AnonymousUser"; expected "User | None" [arg-type] +posthog/api/person.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/person.py:0: error: Argument "user" to "log_activity" has incompatible type "User | AnonymousUser"; expected "User | None" [arg-type] +posthog/api/person.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/person.py:0: error: Cannot determine type of "group_properties_filter_group" [has-type] +posthog/caching/insight_caching_state.py:0: error: Argument "params" to "execute" of "CursorWrapper" has incompatible type "list[object]"; expected "Sequence[bool | int | float | Decimal | str | <6 more items> | None] | Mapping[str, bool | int | float | Decimal | str | <6 more items> | None] | None" [arg-type] posthog/api/cohort.py:0: error: Incompatible type for lookup 'pk': (got "str | int | list[str]", expected "str | int") [misc] +posthog/api/cohort.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] +posthog/api/cohort.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/cohort.py:0: error: Incompatible type for lookup 'pk': (got "str | int | list[str]", expected "str | int") [misc] +posthog/caching/insights_api.py:0: error: Unsupported operand types for >= ("datetime" and "None") [operator] +posthog/caching/insights_api.py:0: note: Right operand is of type "datetime | None" posthog/api/feature_flag.py:0: error: Item "Sequence[Any]" of "Any | Sequence[Any] | None" has no attribute "filters" [union-attr] posthog/api/feature_flag.py:0: error: Item "None" of "Any | Sequence[Any] | None" has no attribute "filters" [union-attr] posthog/api/feature_flag.py:0: error: Incompatible type for lookup 'pk': (got "str | int | list[str]", expected "str | int") [misc] +posthog/api/feature_flag.py:0: error: Argument 2 to "get_all_feature_flags" has incompatible type "str | None"; expected "str" [arg-type] +posthog/api/feature_flag.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] +posthog/api/feature_flag.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/hogql_queries/web_analytics/web_analytics_query_runner.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/hogql_queries/web_analytics/web_analytics_query_runner.py:0: error: Argument 1 to "append" of "list" has incompatible type "EventPropertyFilter"; expected "Expr" [arg-type] posthog/hogql_queries/insights/trends/trends_query_runner.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] @@ -327,15 +417,24 @@ posthog/hogql_queries/insights/lifecycle_query_runner.py:0: error: Item "SelectU posthog/hogql_queries/insights/lifecycle_query_runner.py:0: error: Item "None" of "JoinExpr | Any | None" has no attribute "sample" [union-attr] posthog/hogql_queries/insights/funnels/funnels_query_runner.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/api/survey.py:0: error: Incompatible types in assignment (expression has type "Any | Sequence[Any] | None", variable has type "Survey | None") [assignment] +posthog/api/survey.py:0: error: Argument "item_id" to "log_activity" has incompatible type "UUID"; expected "int | str | UUIDT | None" [arg-type] +posthog/api/survey.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] posthog/api/survey.py:0: error: Item "list[_ErrorFullDetails]" of "_FullDetailDict | list[_ErrorFullDetails] | dict[str, _ErrorFullDetails]" has no attribute "get" [union-attr] posthog/api/survey.py:0: error: Item "object" of "object | Any" has no attribute "__iter__" (not iterable) [union-attr] posthog/hogql_queries/web_analytics/web_overview.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/hogql_queries/web_analytics/top_clicks.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] +posthog/api/user.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/api/user.py:0: error: Module has no attribute "utc" [attr-defined] posthog/api/user.py:0: error: "User" has no attribute "social_auth" [attr-defined] +ee/clickhouse/queries/related_actors_query.py:0: error: Argument 1 to "_query_related_groups" of "RelatedActorsQuery" has incompatible type "int"; expected "Literal[0, 1, 2, 3, 4]" [arg-type] ee/api/test/base.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "License") [assignment] ee/api/test/base.py:0: error: "setUpTestData" undefined in superclass [misc] posthog/warehouse/external_data_source/jobs.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "Status") [assignment] posthog/warehouse/external_data_source/jobs.py:0: error: Incompatible type for lookup 'id': (got "UUID | None", expected "UUID | str") [misc] +posthog/warehouse/api/test/test_table.py:0: error: Item "None" of "DataWarehouseCredential | None" has no attribute "access_key" [union-attr] +posthog/warehouse/api/test/test_table.py:0: error: Item "None" of "DataWarehouseCredential | None" has no attribute "access_secret" [union-attr] +posthog/warehouse/api/test/test_table.py:0: error: Item "None" of "DataWarehouseCredential | None" has no attribute "access_key" [union-attr] +posthog/warehouse/api/test/test_table.py:0: error: Item "None" of "DataWarehouseCredential | None" has no attribute "access_secret" [union-attr] posthog/test/test_utils.py:0: error: Argument 5 to "post" of "_RequestFactory" has incompatible type "**dict[str, str]"; expected "Mapping[str, Any] | None" [arg-type] posthog/test/test_plugin_log_entry.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/test/test_plugin_log_entry.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] @@ -346,6 +445,25 @@ posthog/test/test_health.py:0: error: "HttpResponse" has no attribute "json" [a posthog/test/test_health.py:0: error: "HttpResponse" has no attribute "json" [attr-defined] posthog/test/test_health.py:0: error: Incompatible return value type (got "_MonkeyPatchedWSGIResponse", expected "HttpResponse") [return-value] posthog/test/test_health.py:0: error: Incompatible return value type (got "_MonkeyPatchedWSGIResponse", expected "HttpResponse") [return-value] +posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard | None" has no attribute "name" [union-attr] +posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard | None" has no attribute "name" [union-attr] +posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard | None" has no attribute "tiles" [union-attr] +posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard | None" has no attribute "tiles" [union-attr] +posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard | None" has no attribute "delete" [union-attr] +posthog/test/activity_logging/test_activity_logging.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] +posthog/test/activity_logging/test_activity_logging.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] +posthog/test/activity_logging/test_activity_logging.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] +posthog/tasks/test/test_update_survey_iteration.py:0: error: Item "None" of "FeatureFlag | None" has no attribute "filters" [union-attr] +posthog/tasks/test/test_stop_surveys_reached_target.py:0: error: No overload variant of "__sub__" of "datetime" matches argument type "None" [operator] +posthog/tasks/test/test_stop_surveys_reached_target.py:0: note: Possible overload variants: +posthog/tasks/test/test_stop_surveys_reached_target.py:0: note: def __sub__(self, datetime, /) -> timedelta +posthog/tasks/test/test_stop_surveys_reached_target.py:0: note: def __sub__(self, timedelta, /) -> datetime +posthog/tasks/test/test_stop_surveys_reached_target.py:0: note: Right operand is of type "datetime | None" +posthog/tasks/test/test_stop_surveys_reached_target.py:0: error: No overload variant of "__sub__" of "datetime" matches argument type "None" [operator] +posthog/tasks/test/test_stop_surveys_reached_target.py:0: note: Possible overload variants: +posthog/tasks/test/test_stop_surveys_reached_target.py:0: note: def __sub__(self, datetime, /) -> timedelta +posthog/tasks/test/test_stop_surveys_reached_target.py:0: note: def __sub__(self, timedelta, /) -> datetime +posthog/tasks/test/test_stop_surveys_reached_target.py:0: note: Right operand is of type "datetime | None" posthog/tasks/exports/test/test_image_exporter.py:0: error: Function is missing a type annotation [no-untyped-def] posthog/tasks/exports/test/test_image_exporter.py:0: error: Function is missing a type annotation [no-untyped-def] posthog/tasks/exports/test/test_image_exporter.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def] @@ -357,6 +475,10 @@ posthog/tasks/exports/test/test_export_utils.py:0: error: Function is missing a posthog/tasks/exports/test/test_csv_exporter_url_sanitising.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def] posthog/tasks/exports/test/test_csv_exporter_url_sanitising.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def] posthog/tasks/exports/test/test_csv_exporter_renders.py:0: error: Function is missing a type annotation [no-untyped-def] +posthog/tasks/exports/test/test_csv_exporter_renders.py:0: error: Item "memoryview" of "bytes | memoryview | None" has no attribute "decode" [union-attr] +posthog/tasks/exports/test/test_csv_exporter_renders.py:0: error: Item "None" of "bytes | memoryview | None" has no attribute "decode" [union-attr] +posthog/tasks/exports/test/test_csv_exporter_renders.py:0: error: Item "memoryview" of "bytes | memoryview | None" has no attribute "decode" [union-attr] +posthog/tasks/exports/test/test_csv_exporter_renders.py:0: error: Item "None" of "bytes | memoryview | None" has no attribute "decode" [union-attr] posthog/hogql_queries/test/test_query_runner.py:0: error: Variable "TestQueryRunner" is not valid as a type [valid-type] posthog/hogql_queries/test/test_query_runner.py:0: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases posthog/hogql_queries/test/test_query_runner.py:0: error: Invalid base class "TestQueryRunner" [misc] @@ -379,13 +501,13 @@ posthog/hogql/test/test_timings.py:0: note: def __setitem__(self, slice, Iterabl posthog/hogql/test/test_timings.py:0: error: Signature of "assertAlmostEquals" incompatible with supertype "TestCase" [override] posthog/hogql/test/test_timings.py:0: note: Superclass: posthog/hogql/test/test_timings.py:0: note: @overload -posthog/hogql/test/test_timings.py:0: note: def [_S: SupportsSub[Any, Any]] assertAlmostEqual(self: TestCase, first: _S, second: _S, places: None, msg: Any, delta: _SupportsAbsAndDunderGE) -> None +posthog/hogql/test/test_timings.py:0: note: def [_S: SupportsSub[Any, Any]] (self: TestCase, first: _S, second: _S, places: None, msg: Any, delta: _SupportsAbsAndDunderGE) -> None posthog/hogql/test/test_timings.py:0: note: @overload -posthog/hogql/test/test_timings.py:0: note: def [_S: SupportsSub[Any, Any]] assertAlmostEqual(self: TestCase, first: _S, second: _S, places: None = ..., msg: Any = ..., *, delta: _SupportsAbsAndDunderGE) -> None +posthog/hogql/test/test_timings.py:0: note: def [_S: SupportsSub[Any, Any]] (self: TestCase, first: _S, second: _S, places: None = ..., msg: Any = ..., *, delta: _SupportsAbsAndDunderGE) -> None posthog/hogql/test/test_timings.py:0: note: @overload -posthog/hogql/test/test_timings.py:0: note: def [_T] assertAlmostEqual(self: TestCase, first: SupportsSub[_T, SupportsAbs[SupportsRound[object]]], second: _T, places: int | None = ..., msg: Any = ..., delta: None = ...) -> None +posthog/hogql/test/test_timings.py:0: note: def [_T] (self: TestCase, first: SupportsSub[_T, SupportsAbs[SupportsRound[object]]], second: _T, places: int | None = ..., msg: Any = ..., delta: None = ...) -> None posthog/hogql/test/test_timings.py:0: note: @overload -posthog/hogql/test/test_timings.py:0: note: def [_T] assertAlmostEqual(self: TestCase, first: _T, second: SupportsRSub[_T, SupportsAbs[SupportsRound[object]]], places: int | None = ..., msg: Any = ..., delta: None = ...) -> None +posthog/hogql/test/test_timings.py:0: note: def [_T] (self: TestCase, first: _T, second: SupportsRSub[_T, SupportsAbs[SupportsRound[object]]], places: int | None = ..., msg: Any = ..., delta: None = ...) -> None posthog/hogql/test/test_timings.py:0: note: Subclass: posthog/hogql/test/test_timings.py:0: note: def assertAlmostEquals(self, a: Any, b: Any, epsilon: Any = ...) -> Any posthog/hogql/test/test_resolver.py:0: error: Item "None" of "JoinExpr | None" has no attribute "next_join" [union-attr] @@ -445,14 +567,32 @@ posthog/heatmaps/test/test_heatmaps_api.py:0: error: "HttpResponse" has no attri posthog/heatmaps/test/test_heatmaps_api.py:0: error: "HttpResponse" has no attribute "json" [attr-defined] posthog/heatmaps/test/test_heatmaps_api.py:0: error: "HttpResponse" has no attribute "json" [attr-defined] posthog/heatmaps/test/test_heatmaps_api.py:0: error: "HttpResponse" has no attribute "json" [attr-defined] +posthog/api/uploaded_media.py:0: error: Argument 1 to "read_bytes" has incompatible type "str | None"; expected "str" [arg-type] +posthog/api/uploaded_media.py:0: error: Argument 1 to "read_bytes" has incompatible type "str | None"; expected "str" [arg-type] posthog/api/test/test_utils.py:0: error: Incompatible types in assignment (expression has type "dict[str, str]", variable has type "QueryDict") [assignment] +posthog/api/test/test_survey.py:0: error: Item "None" of "FeatureFlag | None" has no attribute "active" [union-attr] +posthog/api/test/test_stickiness.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/api/test/test_stickiness.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/api/test/test_stickiness.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/api/test/test_stickiness.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/api/test/test_stickiness.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/api/test/test_stickiness.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/api/test/test_stickiness.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/api/test/test_stickiness.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/api/test/test_stickiness.py:0: error: Module has no attribute "utc" [attr-defined] posthog/api/test/test_signup.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/api/test/test_signup.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/api/test/test_signup.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/api/test/test_signup.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/api/test/test_preflight.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] posthog/api/test/test_preflight.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] +posthog/api/test/test_personal_api_keys.py:0: error: Item "None" of "str | None" has no attribute "startswith" [union-attr] +posthog/api/test/test_personal_api_keys.py:0: error: Item "None" of "str | None" has no attribute "startswith" [union-attr] posthog/api/test/test_person.py:0: error: Argument "data" to "get" of "APIClient" has incompatible type "dict[str, object]"; expected "Mapping[str, str | bytes | int | Iterable[str | bytes | int]] | Iterable[tuple[str, str | bytes | int | Iterable[str | bytes | int]]] | None" [arg-type] +posthog/api/test/test_organization_domain.py:0: error: Item "None" of "datetime | None" has no attribute "strftime" [union-attr] +posthog/api/signup.py:0: error: Argument 1 to "create_user" of "UserManager" has incompatible type "str | None"; expected "str" [arg-type] +posthog/api/organization_member.py:0: error: "User" has no attribute "totpdevice_set" [attr-defined] +posthog/api/organization_member.py:0: error: "User" has no attribute "social_auth" [attr-defined] posthog/api/organization_member.py:0: error: Signature of "update" incompatible with supertype "ModelSerializer" [override] posthog/api/organization_member.py:0: note: Superclass: posthog/api/organization_member.py:0: note: def update(self, instance: Any, validated_data: Any) -> Any @@ -463,9 +603,22 @@ posthog/api/organization_member.py:0: note: Superclass: posthog/api/organization_member.py:0: note: def update(self, instance: Any, validated_data: Any) -> Any posthog/api/organization_member.py:0: note: Subclass: posthog/api/organization_member.py:0: note: def update(self, updated_membership: Any, validated_data: Any, **kwargs: Any) -> Any +posthog/api/organization_feature_flag.py:0: error: Invalid index type "str | None" for "dict[str, int]"; expected type "str" [index] +posthog/api/organization_feature_flag.py:0: error: Invalid index type "str | None" for "dict[str, int]"; expected type "str" [index] +posthog/api/organization_feature_flag.py:0: error: Invalid index type "str | None" for "dict[str, int]"; expected type "str" [index] posthog/api/notebook.py:0: error: Incompatible types in assignment (expression has type "int", variable has type "str | None") [assignment] +posthog/api/exports.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] +posthog/warehouse/data_load/validate_schema.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "DataWarehouseCredential | Combinable | None") [assignment] +posthog/warehouse/data_load/validate_schema.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "str | int | Combinable") [assignment] posthog/warehouse/data_load/validate_schema.py:0: error: Incompatible types in assignment (expression has type "dict[str, dict[str, str | bool]] | dict[str, str]", variable has type "dict[str, dict[str, str]]") [assignment] -posthog/temporal/data_imports/workflow_activities/create_job_model.py:0: error: Incompatible types in assignment (expression has type "list[str]", variable has type "dict[str, list[tuple[str, str]]]") [assignment] +posthog/warehouse/data_load/source_templates.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "Type") [assignment] +posthog/temporal/data_imports/workflow_activities/create_job_model.py:0: error: Argument 1 has incompatible type "str"; expected "Type" [arg-type] +posthog/temporal/data_imports/workflow_activities/create_job_model.py:0: error: Incompatible types in assignment (expression has type "list[Any]", variable has type "dict[str, list[tuple[str, str]]]") [assignment] +posthog/temporal/data_imports/workflow_activities/create_job_model.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "tuple[()]" [call-overload] +posthog/temporal/data_imports/workflow_activities/create_job_model.py:0: note: Possible overload variants: +posthog/temporal/data_imports/workflow_activities/create_job_model.py:0: note: def get(self, Type, /) -> Sequence[str] | None +posthog/temporal/data_imports/workflow_activities/create_job_model.py:0: note: def get(self, Type, Sequence[str], /) -> Sequence[str] +posthog/temporal/data_imports/workflow_activities/create_job_model.py:0: note: def [_T] get(self, Type, _T, /) -> Sequence[str] | _T posthog/temporal/data_imports/workflow_activities/create_job_model.py:0: error: Argument 1 has incompatible type "dict[str, list[tuple[str, str]]]"; expected "list[Any]" [arg-type] posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Not all union combinations were tried because there are too many unions [misc] posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 2 to "source" has incompatible type "str | None"; expected "str" [arg-type] @@ -491,10 +644,16 @@ posthog/tasks/exports/test/test_csv_exporter.py:0: error: Function is missing a posthog/tasks/exports/test/test_csv_exporter.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def] posthog/tasks/exports/test/test_csv_exporter.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def] posthog/tasks/exports/test/test_csv_exporter.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def] +posthog/tasks/exports/test/test_csv_exporter.py:0: error: Argument 1 to "BytesIO" has incompatible type "bytes | memoryview | None"; expected "Buffer" [arg-type] posthog/tasks/exports/test/test_csv_exporter.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def] posthog/tasks/exports/test/test_csv_exporter.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def] posthog/tasks/exports/test/test_csv_exporter.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def] posthog/tasks/exports/test/test_csv_exporter.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def] +posthog/tasks/exports/test/test_csv_exporter.py:0: error: Argument 1 to "read" has incompatible type "str | None"; expected "str" [arg-type] +posthog/tasks/exports/test/test_csv_exporter.py:0: error: Argument 1 to "read" has incompatible type "str | None"; expected "str" [arg-type] +posthog/tasks/exports/test/test_csv_exporter.py:0: error: Argument 1 to "read" has incompatible type "str | None"; expected "str" [arg-type] +posthog/tasks/exports/test/test_csv_exporter.py:0: error: Argument 1 to "read" has incompatible type "str | None"; expected "str" [arg-type] +posthog/tasks/exports/test/test_csv_exporter.py:0: error: Argument 1 to "read" has incompatible type "str | None"; expected "str" [arg-type] posthog/queries/trends/test/test_person.py:0: error: "str" has no attribute "get" [attr-defined] posthog/queries/trends/test/test_person.py:0: error: Invalid index type "int" for "_MonkeyPatchedResponse"; expected type "str" [index] posthog/queries/trends/test/test_person.py:0: error: "str" has no attribute "get" [attr-defined] @@ -518,14 +677,29 @@ posthog/queries/trends/test/test_person.py:0: error: Invalid index type "int" fo posthog/queries/trends/test/test_person.py:0: error: "str" has no attribute "get" [attr-defined] posthog/queries/trends/test/test_person.py:0: error: Invalid index type "int" for "_MonkeyPatchedResponse"; expected type "str" [index] posthog/models/test/test_organization_model.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] +posthog/management/commands/sync_persons_to_clickhouse.py:0: error: Argument 4 to "create_person_override" has incompatible type "int | None"; expected "int" [arg-type] posthog/management/commands/sync_persons_to_clickhouse.py:0: error: Argument "group_type_index" to "raw_create_group_ch" has incompatible type "int"; expected "Literal[0, 1, 2, 3, 4]" [arg-type] posthog/management/commands/migrate_team.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "BatchExport") [assignment] +posthog/management/commands/migrate_team.py:0: error: "BatchExportDestination" has no attribute "exclude_events" [attr-defined] +posthog/management/commands/migrate_team.py:0: error: "BatchExportDestination" has no attribute "include_events" [attr-defined] +posthog/management/commands/migrate_action_webhooks.py:0: error: Argument 1 to "convert_link" has incompatible type "str | None"; expected "str" [arg-type] +posthog/management/commands/migrate_action_webhooks.py:0: error: Argument 2 to "replace" of "str" has incompatible type "str | None"; expected "str" [arg-type] +posthog/management/commands/fix_future_person_created_at.py:0: error: Argument "version" to "create_person" has incompatible type "int | None"; expected "int" [arg-type] posthog/hogql/test/test_query.py:0: error: Value of type "list[QueryTiming] | None" is not indexable [index] posthog/hogql/test/test_query.py:0: error: Value of type "list[QueryTiming] | None" is not indexable [index] +posthog/hogql/test/test_query.py:0: error: Module has no attribute "utc" [attr-defined] posthog/hogql/test/test_query.py:0: error: Argument 1 to "pretty_print_in_tests" has incompatible type "str | None"; expected "str" [arg-type] posthog/hogql/test/test_query.py:0: error: Argument 1 to "pretty_print_in_tests" has incompatible type "str | None"; expected "str" [arg-type] posthog/hogql/test/test_query.py:0: error: Argument 1 to "pretty_print_in_tests" has incompatible type "str | None"; expected "str" [arg-type] posthog/hogql/test/test_query.py:0: error: Argument 1 to "pretty_print_in_tests" has incompatible type "str | None"; expected "str" [arg-type] +posthog/hogql/test/test_query.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/hogql/test/test_query.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/hogql/test/test_query.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/hogql/test/test_query.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/hogql/test/test_query.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/hogql/test/test_query.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/hogql/test/test_query.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/hogql/test/test_query.py:0: error: Module has no attribute "utc" [attr-defined] posthog/hogql/test/test_query.py:0: error: Argument "placeholders" to "execute_hogql_query" has incompatible type "dict[str, Constant]"; expected "dict[str, Expr] | None" [arg-type] posthog/hogql/test/test_query.py:0: note: "Dict" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance posthog/hogql/test/test_query.py:0: note: Consider using "Mapping" instead, which is covariant in the value type @@ -543,6 +717,18 @@ posthog/hogql/test/test_parse_string_python.py:0: error: Unsupported dynamic bas posthog/hogql/test/test_parse_string_cpp.py:0: error: Unsupported dynamic base class "parse_string_test_factory" [misc] posthog/hogql/database/test/test_view.py:0: error: Argument "dialect" to "print_ast" has incompatible type "str"; expected "Literal['hogql', 'clickhouse']" [arg-type] posthog/hogql/database/test/test_s3_table.py:0: error: Argument "dialect" to "print_ast" has incompatible type "str"; expected "Literal['hogql', 'clickhouse']" [arg-type] +posthog/async_migrations/test/test_runner.py:0: error: Item "None" of "datetime | None" has no attribute "day" [union-attr] +posthog/api/test/test_insight.py:0: error: Argument "data" to "get" of "APIClient" has incompatible type "dict[str, object]"; expected "Mapping[str, str | bytes | int | Iterable[str | bytes | int]] | Iterable[tuple[str, str | bytes | int | Iterable[str | bytes | int]]] | None" [arg-type] +posthog/api/test/test_insight.py:0: error: Argument "data" to "get" of "APIClient" has incompatible type "dict[str, object]"; expected "Mapping[str, str | bytes | int | Iterable[str | bytes | int]] | Iterable[tuple[str, str | bytes | int | Iterable[str | bytes | int]]] | None" [arg-type] +posthog/api/test/test_feature_flag.py:0: error: Item "None" of "Dashboard | None" has no attribute "tiles" [union-attr] +posthog/api/test/test_feature_flag.py:0: error: Item "None" of "Dashboard | None" has no attribute "name" [union-attr] +posthog/api/test/test_feature_flag.py:0: error: Item "None" of "Dashboard | None" has no attribute "description" [union-attr] +posthog/api/test/test_feature_flag.py:0: error: Item "None" of "Dashboard | None" has no attribute "filters" [union-attr] +posthog/api/test/test_feature_flag.py:0: error: Item "None" of "Dashboard | None" has no attribute "tiles" [union-attr] +posthog/api/test/test_feature_flag.py:0: error: Item "None" of "Dashboard | None" has no attribute "name" [union-attr] +posthog/api/test/test_feature_flag.py:0: error: Item "None" of "Dashboard | None" has no attribute "description" [union-attr] +posthog/api/test/test_feature_flag.py:0: error: Item "None" of "Dashboard | None" has no attribute "filters" [union-attr] +posthog/api/test/dashboards/test_dashboard.py:0: error: Value of type variable "_S" of "assertAlmostEqual" of "TestCase" cannot be "datetime | None" [type-var] posthog/api/test/dashboards/test_dashboard.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] posthog/api/test/dashboards/test_dashboard.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] posthog/api/test/dashboards/test_dashboard.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] @@ -556,7 +742,7 @@ posthog/api/property_definition.py:0: error: Item "AnonymousUser" of "User | Ano posthog/api/property_definition.py:0: error: Item "None" of "Organization | Any | None" has no attribute "is_feature_available" [union-attr] posthog/api/property_definition.py:0: error: Item "ForeignObjectRel" of "Field[Any, Any] | ForeignObjectRel | GenericForeignKey" has no attribute "cached_col" [union-attr] posthog/api/property_definition.py:0: error: Item "GenericForeignKey" of "Field[Any, Any] | ForeignObjectRel | GenericForeignKey" has no attribute "cached_col" [union-attr] -posthog/api/property_definition.py:0: error: Incompatible types in assignment (expression has type "Manager[EnterprisePropertyDefinition]", variable has type "_QuerySet[PropertyDefinition, PropertyDefinition]") [assignment] +posthog/api/property_definition.py:0: error: Incompatible types in assignment (expression has type "Manager[EnterprisePropertyDefinition]", variable has type "QuerySet[PropertyDefinition, PropertyDefinition]") [assignment] posthog/api/property_definition.py:0: error: Item "BasePagination" of "BasePagination | None" has no attribute "get_limit" [union-attr] posthog/api/property_definition.py:0: error: Item "None" of "BasePagination | None" has no attribute "get_limit" [union-attr] posthog/api/property_definition.py:0: error: Item "BasePagination" of "BasePagination | None" has no attribute "get_offset" [union-attr] @@ -594,6 +780,14 @@ posthog/admin/inlines/plugin_attachment_inline.py:0: note: Superclass: posthog/admin/inlines/plugin_attachment_inline.py:0: note: def has_delete_permission(self, request: HttpRequest, obj: Any | None = ...) -> bool posthog/admin/inlines/plugin_attachment_inline.py:0: note: Subclass: posthog/admin/inlines/plugin_attachment_inline.py:0: note: def has_delete_permission(self, request: Any, obj: Any) -> Any +posthog/admin/admins/team_admin.py:0: error: Item "None" of "Project | None" has no attribute "pk" [union-attr] +posthog/admin/admins/team_admin.py:0: error: Item "None" of "Project | None" has no attribute "name" [union-attr] +posthog/admin/admins/plugin_admin.py:0: error: Item "None" of "Organization | None" has no attribute "pk" [union-attr] +posthog/admin/admins/plugin_admin.py:0: error: Item "None" of "Organization | None" has no attribute "name" [union-attr] +ee/clickhouse/views/experiments.py:0: error: Argument 4 to "ClickhouseTrendExperimentResult" has incompatible type "datetime | None"; expected "datetime" [arg-type] +ee/clickhouse/views/experiments.py:0: error: Argument 4 to "ClickhouseFunnelExperimentResult" has incompatible type "datetime | None"; expected "datetime" [arg-type] +ee/clickhouse/views/experiments.py:0: error: Argument 4 to "ClickhouseSecondaryExperimentResult" has incompatible type "datetime | None"; expected "datetime" [arg-type] +ee/clickhouse/views/experiments.py:0: error: Item "None" of "User | None" has no attribute "email" [union-attr] posthog/temporal/tests/batch_exports/test_run_updates.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/tests/batch_exports/test_run_updates.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/tests/batch_exports/test_run_updates.py:0: error: Unused "type: ignore" comment [unused-ignore] @@ -615,14 +809,45 @@ posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "typ posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/data_imports/pipelines/stripe/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/tasks/test/test_email.py:0: error: Argument 1 to "send_batch_export_run_failure" has incompatible type "UUID"; expected "str" [arg-type] +posthog/tasks/test/test_email.py:0: error: Argument 1 to "send_batch_export_run_failure" has incompatible type "UUID"; expected "str" [arg-type] +posthog/tasks/test/test_email.py:0: error: Argument 1 to "send_batch_export_run_failure" has incompatible type "UUID"; expected "str" [arg-type] posthog/session_recordings/session_recording_api.py:0: error: Argument "team_id" to "get_realtime_snapshots" has incompatible type "int"; expected "str" [arg-type] +posthog/session_recordings/session_recording_api.py:0: error: Value of type variable "SupportsRichComparisonT" of "sorted" cannot be "str | None" [type-var] +posthog/session_recordings/session_recording_api.py:0: error: Argument 1 to "get" of "dict" has incompatible type "str | None"; expected "str" [arg-type] posthog/queries/app_metrics/test/test_app_metrics.py:0: error: Argument 3 to "AppMetricsErrorDetailsQuery" has incompatible type "AppMetricsRequestSerializer"; expected "AppMetricsErrorsRequestSerializer" [arg-type] posthog/queries/app_metrics/test/test_app_metrics.py:0: error: Argument 3 to "AppMetricsErrorDetailsQuery" has incompatible type "AppMetricsRequestSerializer"; expected "AppMetricsErrorsRequestSerializer" [arg-type] posthog/queries/app_metrics/test/test_app_metrics.py:0: error: Argument 3 to "AppMetricsErrorDetailsQuery" has incompatible type "AppMetricsRequestSerializer"; expected "AppMetricsErrorsRequestSerializer" [arg-type] -posthog/api/test/test_decide.py:0: error: Item "None" of "Any | None" has no attribute "toolbar_mode" [union-attr] -posthog/api/test/test_decide.py:0: error: Item "None" of "Any | None" has no attribute "save" [union-attr] +posthog/queries/app_metrics/historical_exports.py:0: error: Argument 1 to "loads" has incompatible type "str | None"; expected "str | bytes | bytearray" [arg-type] +posthog/api/test/test_decide.py:0: error: Item "None" of "User | None" has no attribute "toolbar_mode" [union-attr] +posthog/api/test/test_decide.py:0: error: Item "None" of "User | None" has no attribute "save" [union-attr] +posthog/api/test/test_authentication.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "organization" [union-attr] +posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID | Any"; expected "UUIDT | None" [arg-type] +posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "id" [union-attr] +posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "organization" [union-attr] +posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID | Any"; expected "UUIDT | None" [arg-type] +posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "id" [union-attr] +posthog/api/plugin.py:0: error: Incompatible types in assignment (expression has type "str | None", variable has type "str | int | Combinable") [assignment] +posthog/api/plugin.py:0: error: Incompatible types in assignment (expression has type "str | None", variable has type "str | int | Combinable") [assignment] +posthog/api/plugin.py:0: error: Incompatible types in assignment (expression has type "int | None", variable has type "float | int | str | Combinable") [assignment] posthog/api/plugin.py:0: error: Item "None" of "IO[Any] | None" has no attribute "read" [union-attr] +posthog/api/plugin.py:0: error: Incompatible type for "file_name" of "PluginAttachment" (got "str | None", expected "str | int | Combinable") [misc] +posthog/api/plugin.py:0: error: Incompatible type for "file_size" of "PluginAttachment" (got "int | None", expected "float | int | str | Combinable") [misc] posthog/api/plugin.py:0: error: Item "None" of "IO[Any] | None" has no attribute "read" [union-attr] +posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "organization" [union-attr] +posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID | Any"; expected "UUIDT | None" [arg-type] +posthog/api/plugin.py:0: error: Item "None" of "Team | None" has no attribute "id" [union-attr] +posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] +posthog/api/plugin.py:0: error: Argument "organization_id" to "log_activity" has incompatible type "UUID"; expected "UUIDT | None" [arg-type] +posthog/admin/admins/plugin_config_admin.py:0: error: Item "None" of "Team | None" has no attribute "name" [union-attr] +posthog/warehouse/api/external_data_schema.py:0: error: Incompatible return value type (got "str | None", expected "SyncType | None") [return-value] +posthog/warehouse/api/external_data_schema.py:0: error: Argument 1 to "get_sql_schemas_for_source_type" has incompatible type "str"; expected "Type" [arg-type] +posthog/warehouse/api/external_data_schema.py:0: error: No overload variant of "get" of "dict" matches argument type "str" [call-overload] +posthog/warehouse/api/external_data_schema.py:0: note: Possible overload variants: +posthog/warehouse/api/external_data_schema.py:0: note: def get(self, Type, /) -> dict[str, list[IncrementalField]] | None +posthog/warehouse/api/external_data_schema.py:0: note: def get(self, Type, dict[str, list[IncrementalField]], /) -> dict[str, list[IncrementalField]] +posthog/warehouse/api/external_data_schema.py:0: note: def [_T] get(self, Type, _T, /) -> dict[str, list[IncrementalField]] | _T posthog/warehouse/api/external_data_source.py:0: error: Incompatible return value type (got "tuple[ExternalDataSource, dict[str, list[tuple[str, str]]]]", expected "tuple[ExternalDataSource, list[Any]]") [return-value] posthog/warehouse/api/external_data_source.py:0: error: Incompatible return value type (got "tuple[ExternalDataSource, dict[str, list[tuple[str, str]]]]", expected "tuple[ExternalDataSource, list[Any]]") [return-value] posthog/warehouse/api/table.py:0: error: Unused "type: ignore" comment [unused-ignore] @@ -632,6 +857,9 @@ posthog/temporal/tests/batch_exports/test_snowflake_batch_export_workflow.py:0: posthog/temporal/tests/batch_exports/test_snowflake_batch_export_workflow.py:0: error: List item 0 has incompatible type "tuple[str, str, int, int, int, int, str, int]"; expected "tuple[str, str, int, int, str, str, str, str]" [list-item] posthog/temporal/tests/batch_exports/test_s3_batch_export_workflow.py:0: error: "tuple[Any, ...]" has no attribute "last_uploaded_part_timestamp" [attr-defined] posthog/temporal/tests/batch_exports/test_s3_batch_export_workflow.py:0: error: "tuple[Any, ...]" has no attribute "upload_state" [attr-defined] +posthog/temporal/data_imports/workflow_activities/import_data.py:0: error: Argument "job_type" to "PipelineInputs" has incompatible type "str"; expected "Type" [arg-type] +posthog/temporal/data_imports/workflow_activities/import_data.py:0: error: Argument "source_type" to "sql_source_for_type" has incompatible type "str"; expected "Type" [arg-type] +posthog/temporal/data_imports/workflow_activities/import_data.py:0: error: Argument "source_type" to "sql_source_for_type" has incompatible type "str"; expected "Type" [arg-type] posthog/migrations/0237_remove_timezone_from_teams.py:0: error: Argument 2 to "RunPython" has incompatible type "Callable[[Migration, Any], None]"; expected "_CodeCallable | None" [arg-type] posthog/migrations/0228_fix_tile_layouts.py:0: error: Argument 2 to "RunPython" has incompatible type "Callable[[Migration, Any], None]"; expected "_CodeCallable | None" [arg-type] posthog/api/plugin_log_entry.py:0: error: Name "timezone.datetime" is not defined [name-defined] @@ -643,6 +871,12 @@ posthog/warehouse/external_data_source/source.py:0: error: Incompatible types in posthog/warehouse/external_data_source/source.py:0: error: Incompatible types in assignment (expression has type "dict[str, Collection[str]]", variable has type "StripeSourcePayload") [assignment] posthog/warehouse/external_data_source/source.py:0: error: Argument 1 to "_create_source" has incompatible type "StripeSourcePayload"; expected "dict[Any, Any]" [arg-type] posthog/temporal/tests/batch_exports/test_redshift_batch_export_workflow.py:0: error: Incompatible types in assignment (expression has type "str | int", variable has type "int") [assignment] +posthog/api/sharing.py:0: error: Item "None" of "list[Any] | None" has no attribute "__iter__" (not iterable) [union-attr] +posthog/temporal/tests/external_data/test_external_data_job.py:0: error: Invalid index type "str" for "dict[Type, Sequence[str]]"; expected type "Type" [index] +posthog/temporal/tests/external_data/test_external_data_job.py:0: error: Invalid index type "str" for "dict[Type, Sequence[str]]"; expected type "Type" [index] +posthog/temporal/tests/external_data/test_external_data_job.py:0: error: Invalid index type "str" for "dict[Type, Sequence[str]]"; expected type "Type" [index] +posthog/temporal/tests/external_data/test_external_data_job.py:0: error: Invalid index type "str" for "dict[Type, Sequence[str]]"; expected type "Type" [index] +posthog/temporal/tests/external_data/test_external_data_job.py:0: error: Invalid index type "str" for "dict[Type, Sequence[str]]"; expected type "Type" [index] posthog/api/test/batch_exports/conftest.py:0: error: Signature of "run" incompatible with supertype "Worker" [override] posthog/api/test/batch_exports/conftest.py:0: note: Superclass: posthog/api/test/batch_exports/conftest.py:0: note: def run(self) -> Coroutine[Any, Any, None] @@ -654,12 +888,16 @@ posthog/api/test/test_team.py:0: error: "HttpResponse" has no attribute "json" posthog/api/test/test_team.py:0: error: "HttpResponse" has no attribute "json" [attr-defined] posthog/api/test/test_capture.py:0: error: Statement is unreachable [unreachable] posthog/api/test/test_capture.py:0: error: Incompatible return value type (got "_MonkeyPatchedWSGIResponse", expected "HttpResponse") [return-value] -posthog/api/test/test_capture.py:0: error: Dict entry 0 has incompatible type "Any": "float"; expected "str": "int" [dict-item] -posthog/api/test/test_capture.py:0: error: Dict entry 0 has incompatible type "Any": "float"; expected "str": "int" [dict-item] -posthog/api/test/test_capture.py:0: error: Dict entry 0 has incompatible type "Any": "float"; expected "str": "int" [dict-item] -posthog/api/test/test_capture.py:0: error: Dict entry 0 has incompatible type "Any": "float"; expected "str": "int" [dict-item] -posthog/api/test/test_capture.py:0: error: Dict entry 0 has incompatible type "Any": "float"; expected "str": "int" [dict-item] -posthog/api/test/test_capture.py:0: error: Dict entry 0 has incompatible type "Any": "float"; expected "str": "int" [dict-item] +posthog/api/test/test_capture.py:0: error: Module has no attribute "utc" [attr-defined] +posthog/api/test/test_capture.py:0: error: Unpacked dict entry 0 has incompatible type "Collection[str]"; expected "SupportsKeysAndGetItem[str, dict[Never, Never]]" [dict-item] +posthog/api/test/test_capture.py:0: error: Unpacked dict entry 0 has incompatible type "Collection[str]"; expected "SupportsKeysAndGetItem[str, dict[Never, Never]]" [dict-item] +posthog/api/test/test_capture.py:0: error: Unpacked dict entry 0 has incompatible type "Collection[str]"; expected "SupportsKeysAndGetItem[str, dict[Never, Never]]" [dict-item] +posthog/api/test/test_capture.py:0: error: Dict entry 0 has incompatible type "str": "float"; expected "str": "int" [dict-item] +posthog/api/test/test_capture.py:0: error: Dict entry 0 has incompatible type "str": "float"; expected "str": "int" [dict-item] +posthog/api/test/test_capture.py:0: error: Dict entry 0 has incompatible type "str": "float"; expected "str": "int" [dict-item] +posthog/api/test/test_capture.py:0: error: Dict entry 0 has incompatible type "str": "float"; expected "str": "int" [dict-item] +posthog/api/test/test_capture.py:0: error: Dict entry 0 has incompatible type "str": "float"; expected "str": "int" [dict-item] +posthog/api/test/test_capture.py:0: error: Dict entry 0 has incompatible type "str": "float"; expected "str": "int" [dict-item] posthog/test/test_middleware.py:0: error: Incompatible types in assignment (expression has type "_MonkeyPatchedWSGIResponse", variable has type "_MonkeyPatchedResponse") [assignment] posthog/management/commands/test/test_create_batch_export_from_app.py:0: error: Incompatible return value type (got "dict[str, Collection[str]]", expected "dict[str, str]") [return-value] posthog/management/commands/test/test_create_batch_export_from_app.py:0: error: Incompatible types in assignment (expression has type "dict[str, Collection[str]]", variable has type "dict[str, str]") [assignment] @@ -698,6 +936,7 @@ posthog/management/commands/test/test_create_batch_export_from_app.py:0: note: d posthog/api/test/batch_exports/test_update.py:0: error: Unsupported target for indexed assignment ("Collection[str]") [index] posthog/api/test/batch_exports/test_update.py:0: error: Unsupported target for indexed assignment ("Collection[str]") [index] posthog/api/test/batch_exports/test_update.py:0: error: Dict entry 1 has incompatible type "str": "dict[str, Collection[str]]"; expected "str": "str" [dict-item] +posthog/api/test/batch_exports/test_update.py:0: error: Argument 3 to "get_batch_export_ok" has incompatible type "UUID"; expected "int" [arg-type] posthog/api/test/batch_exports/test_update.py:0: error: Value of type "BatchExport" is not indexable [index] posthog/api/test/batch_exports/test_update.py:0: error: Value of type "BatchExport" is not indexable [index] posthog/api/test/batch_exports/test_update.py:0: error: Value of type "BatchExport" is not indexable [index] diff --git a/posthog/batch_exports/models.py b/posthog/batch_exports/models.py index e27e34ecd3ab7..e319d73db30ab 100644 --- a/posthog/batch_exports/models.py +++ b/posthog/batch_exports/models.py @@ -39,21 +39,21 @@ class Destination(models.TextChoices): "NoOp": set(), } - type: models.CharField = models.CharField( + type = models.CharField( choices=Destination.choices, max_length=64, help_text="A choice of supported BatchExportDestination types.", ) - config: models.JSONField = models.JSONField( + config = models.JSONField( default=dict, blank=True, help_text="A JSON field to store all configuration parameters required to access a BatchExportDestination.", ) - created_at: models.DateTimeField = models.DateTimeField( + created_at = models.DateTimeField( auto_now_add=True, help_text="The timestamp at which this BatchExportDestination was created.", ) - last_updated_at: models.DateTimeField = models.DateTimeField( + last_updated_at = models.DateTimeField( auto_now=True, help_text="The timestamp at which this BatchExportDestination was last updated.", ) @@ -85,31 +85,25 @@ class Status(models.TextChoices): on_delete=models.CASCADE, help_text="The BatchExport this run belongs to.", ) - status: models.CharField = models.CharField( - choices=Status.choices, max_length=64, help_text="The status of this run." - ) - records_completed: models.IntegerField = models.IntegerField( - null=True, help_text="The number of records that have been exported." - ) - latest_error: models.TextField = models.TextField( - null=True, help_text="The latest error that occurred during this run." - ) - data_interval_start: models.DateTimeField = models.DateTimeField(help_text="The start of the data interval.") - data_interval_end: models.DateTimeField = models.DateTimeField(help_text="The end of the data interval.") - cursor: models.TextField = models.TextField(null=True, help_text="An opaque cursor that may be used to resume.") - created_at: models.DateTimeField = models.DateTimeField( + status = models.CharField(choices=Status.choices, max_length=64, help_text="The status of this run.") + records_completed = models.IntegerField(null=True, help_text="The number of records that have been exported.") + latest_error = models.TextField(null=True, help_text="The latest error that occurred during this run.") + data_interval_start = models.DateTimeField(help_text="The start of the data interval.") + data_interval_end = models.DateTimeField(help_text="The end of the data interval.") + cursor = models.TextField(null=True, help_text="An opaque cursor that may be used to resume.") + created_at = models.DateTimeField( auto_now_add=True, help_text="The timestamp at which this BatchExportRun was created.", ) - finished_at: models.DateTimeField = models.DateTimeField( + finished_at = models.DateTimeField( null=True, help_text="The timestamp at which this BatchExportRun finished, successfully or not.", ) - last_updated_at: models.DateTimeField = models.DateTimeField( + last_updated_at = models.DateTimeField( auto_now=True, help_text="The timestamp at which this BatchExportRun was last updated.", ) - records_total_count: models.IntegerField = models.IntegerField( + records_total_count = models.IntegerField( null=True, help_text="The total count of records that should be exported in this BatchExportRun." ) @@ -175,9 +169,9 @@ class Model(models.TextChoices): EVENTS = "events" PERSONS = "persons" - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE, help_text="The team this belongs to.") - name: models.TextField = models.TextField(help_text="A human-readable name for this BatchExport.") - destination: models.ForeignKey = models.ForeignKey( + team = models.ForeignKey("Team", on_delete=models.CASCADE, help_text="The team this belongs to.") + name = models.TextField(help_text="A human-readable name for this BatchExport.") + destination = models.ForeignKey( "BatchExportDestination", on_delete=models.CASCADE, help_text="The destination to export data to.", @@ -191,31 +185,31 @@ class Model(models.TextChoices): ) paused = models.BooleanField(default=False, help_text="Whether this BatchExport is paused or not.") deleted = models.BooleanField(default=False, help_text="Whether this BatchExport is deleted or not.") - created_at: models.DateTimeField = models.DateTimeField( + created_at = models.DateTimeField( auto_now_add=True, help_text="The timestamp at which this BatchExport was created.", ) - last_updated_at: models.DateTimeField = models.DateTimeField( + last_updated_at = models.DateTimeField( auto_now=True, help_text="The timestamp at which this BatchExport was last updated.", ) - last_paused_at: models.DateTimeField = models.DateTimeField( + last_paused_at = models.DateTimeField( null=True, default=None, help_text="The timestamp at which this BatchExport was last paused.", ) - start_at: models.DateTimeField = models.DateTimeField( + start_at = models.DateTimeField( null=True, default=None, help_text="Time before which any Batch Export runs won't be triggered.", ) - end_at: models.DateTimeField = models.DateTimeField( + end_at = models.DateTimeField( null=True, default=None, help_text="Time after which any Batch Export runs won't be triggered.", ) - schema: models.JSONField = models.JSONField( + schema = models.JSONField( null=True, default=None, help_text="A schema of custom fields to select when exporting data.", @@ -265,26 +259,24 @@ class Status(models.TextChoices): RUNNING = "Running" STARTING = "Starting" - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE, help_text="The team this belongs to.") + team = models.ForeignKey("Team", on_delete=models.CASCADE, help_text="The team this belongs to.") batch_export = models.ForeignKey( "BatchExport", on_delete=models.CASCADE, help_text="The BatchExport this backfill belongs to.", ) - start_at: models.DateTimeField = models.DateTimeField(help_text="The start of the data interval.") - end_at: models.DateTimeField = models.DateTimeField(help_text="The end of the data interval.", null=True) - status: models.CharField = models.CharField( - choices=Status.choices, max_length=64, help_text="The status of this backfill." - ) - created_at: models.DateTimeField = models.DateTimeField( + start_at = models.DateTimeField(help_text="The start of the data interval.") + end_at = models.DateTimeField(help_text="The end of the data interval.", null=True) + status = models.CharField(choices=Status.choices, max_length=64, help_text="The status of this backfill.") + created_at = models.DateTimeField( auto_now_add=True, help_text="The timestamp at which this BatchExportBackfill was created.", ) - finished_at: models.DateTimeField = models.DateTimeField( + finished_at = models.DateTimeField( null=True, help_text="The timestamp at which this BatchExportBackfill finished, successfully or not.", ) - last_updated_at: models.DateTimeField = models.DateTimeField( + last_updated_at = models.DateTimeField( auto_now=True, help_text="The timestamp at which this BatchExportBackfill was last updated.", ) diff --git a/posthog/models/_deprecated_prompts.py b/posthog/models/_deprecated_prompts.py index 780703017519e..77f149f37175e 100644 --- a/posthog/models/_deprecated_prompts.py +++ b/posthog/models/_deprecated_prompts.py @@ -5,18 +5,18 @@ # DEPRECATED - DO NOT USE class Prompt(models.Model): - step: models.IntegerField = models.IntegerField() - type: models.CharField = models.CharField(max_length=200) # tooltip, modal, etc - title: models.CharField = models.CharField(max_length=200) - text: models.CharField = models.CharField(max_length=1000) - placement: models.CharField = models.CharField( + step = models.IntegerField() + type = models.CharField(max_length=200) # tooltip, modal, etc + title = models.CharField(max_length=200) + text = models.CharField(max_length=1000) + placement = models.CharField( max_length=200, default="top" ) # top, bottom, left, right, top-start, bottom-start, etc. - buttons: models.JSONField = models.JSONField() - reference: models.CharField = models.CharField( + buttons = models.JSONField() + reference = models.CharField( max_length=200, default=None, null=True ) # should match a `data-attr` reference to attach to a component - icon: models.CharField = models.CharField(max_length=200) # sync with iconMap in frontend + icon = models.CharField(max_length=200) # sync with iconMap in frontend # DEPRECATED - DO NOT USE @@ -26,19 +26,15 @@ class Meta: models.UniqueConstraint(fields=["key"], name="unique_prompt_sequence"), ] - key: models.CharField = models.CharField(max_length=200) - type: models.CharField = models.CharField( - max_length=200 - ) # we use this to toggle different behaviors in the frontend + key = models.CharField(max_length=200) + type = models.CharField(max_length=200) # we use this to toggle different behaviors in the frontend path_match: ArrayField = ArrayField(models.CharField(max_length=200)) # wildcard path to match the current URL path_exclude: ArrayField = ArrayField(models.CharField(max_length=200)) # wildcard path to exclude the current URL - status: models.CharField = models.CharField(max_length=200) # active, inactive, etc - must_have_completed: models.ManyToManyField = models.ManyToManyField("self", blank=True, symmetrical=False) - requires_opt_in: models.BooleanField = models.BooleanField(default=False) - prompts: models.ManyToManyField = models.ManyToManyField(Prompt) - autorun: models.BooleanField = models.BooleanField( - default=True - ) # whether to run this sequence automatically for all users + status = models.CharField(max_length=200) # active, inactive, etc + must_have_completed = models.ManyToManyField("self", blank=True, symmetrical=False) + requires_opt_in = models.BooleanField(default=False) + prompts = models.ManyToManyField(Prompt) + autorun = models.BooleanField(default=True) # whether to run this sequence automatically for all users # DEPRECATED - DO NOT USE @@ -46,10 +42,10 @@ class UserPromptState(models.Model): class Meta: constraints = [models.UniqueConstraint(fields=["user", "sequence"], name="unique_user_prompt_state")] - user: models.ForeignKey = models.ForeignKey("User", on_delete=models.CASCADE) - sequence: models.ForeignKey = models.ForeignKey(PromptSequence, on_delete=models.CASCADE) + user = models.ForeignKey("User", on_delete=models.CASCADE) + sequence = models.ForeignKey(PromptSequence, on_delete=models.CASCADE) - last_updated_at: models.DateTimeField = models.DateTimeField(default=timezone.now) - step: models.IntegerField = models.IntegerField(default=None, null=True) - completed: models.BooleanField = models.BooleanField(default=False) - dismissed: models.BooleanField = models.BooleanField(default=False) + last_updated_at = models.DateTimeField(default=timezone.now) + step = models.IntegerField(default=None, null=True) + completed = models.BooleanField(default=False) + dismissed = models.BooleanField(default=False) diff --git a/posthog/models/action/action.py b/posthog/models/action/action.py index 82c54f44ea167..7dd056663542f 100644 --- a/posthog/models/action/action.py +++ b/posthog/models/action/action.py @@ -33,23 +33,23 @@ class Action(models.Model): class Meta: indexes = [models.Index(fields=["team_id", "-updated_at"])] - name: models.CharField = models.CharField(max_length=400, null=True, blank=True) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - description: models.TextField = models.TextField(blank=True, default="") - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) - deleted: models.BooleanField = models.BooleanField(default=False) - events: models.ManyToManyField = models.ManyToManyField("Event", blank=True) - post_to_slack: models.BooleanField = models.BooleanField(default=False) - slack_message_format: models.CharField = models.CharField(default="", max_length=1200, blank=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) - bytecode: models.JSONField = models.JSONField(null=True, blank=True) - bytecode_error: models.TextField = models.TextField(blank=True, null=True) - steps_json: models.JSONField = models.JSONField(null=True, blank=True) + name = models.CharField(max_length=400, null=True, blank=True) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + description = models.TextField(blank=True, default="") + created_at = models.DateTimeField(auto_now_add=True, blank=True) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) + deleted = models.BooleanField(default=False) + events = models.ManyToManyField("Event", blank=True) + post_to_slack = models.BooleanField(default=False) + slack_message_format = models.CharField(default="", max_length=1200, blank=True) + updated_at = models.DateTimeField(auto_now=True) + bytecode = models.JSONField(null=True, blank=True) + bytecode_error = models.TextField(blank=True, null=True) + steps_json = models.JSONField(null=True, blank=True) # DEPRECATED: these were used before ClickHouse was our database - is_calculating: models.BooleanField = models.BooleanField(default=False) - last_calculated_at: models.DateTimeField = models.DateTimeField(default=timezone.now, blank=True) + is_calculating = models.BooleanField(default=False) + last_calculated_at = models.DateTimeField(default=timezone.now, blank=True) def __str__(self): return self.name diff --git a/posthog/models/action/action_step.py b/posthog/models/action/action_step.py index c2722f87ae07d..975137ba39d16 100644 --- a/posthog/models/action/action_step.py +++ b/posthog/models/action/action_step.py @@ -8,26 +8,26 @@ class ActionStep(models.Model): EXACT = "exact" STRING_MATCHING = [(CONTAINS, CONTAINS), (REGEX, REGEX), (EXACT, EXACT)] - action: models.ForeignKey = models.ForeignKey("Action", related_name="action_steps", on_delete=models.CASCADE) - text: models.CharField = models.CharField(max_length=400, null=True, blank=True) - text_matching: models.CharField = models.CharField( + action = models.ForeignKey("Action", related_name="action_steps", on_delete=models.CASCADE) + text = models.CharField(max_length=400, null=True, blank=True) + text_matching = models.CharField( # The implicit default is EXACT - no explicit default to avoid migration woes max_length=400, choices=STRING_MATCHING, null=True, blank=True, ) - href: models.CharField = models.CharField(max_length=65535, null=True, blank=True) - href_matching: models.CharField = models.CharField( + href = models.CharField(max_length=65535, null=True, blank=True) + href_matching = models.CharField( # The implicit default is EXACT - no explicit default to avoid migration woes max_length=400, choices=STRING_MATCHING, null=True, blank=True, ) - selector: models.CharField = models.CharField(max_length=65535, null=True, blank=True) - url: models.CharField = models.CharField(max_length=65535, null=True, blank=True) - url_matching: models.CharField = models.CharField( + selector = models.CharField(max_length=65535, null=True, blank=True) + url = models.CharField(max_length=65535, null=True, blank=True) + url_matching = models.CharField( # This is from before text_matching and href_matching, which is why there's an explicit default of CONTAINS max_length=400, choices=STRING_MATCHING, @@ -35,9 +35,9 @@ class ActionStep(models.Model): null=True, blank=True, ) - event: models.CharField = models.CharField(max_length=400, null=True, blank=True) - properties: models.JSONField = models.JSONField(default=list, null=True, blank=True) + event = models.CharField(max_length=400, null=True, blank=True) + properties = models.JSONField(default=list, null=True, blank=True) # DEPRECATED, DISUSED - name: models.CharField = models.CharField(max_length=400, null=True, blank=True) + name = models.CharField(max_length=400, null=True, blank=True) # DEPRECATED, don't store new data here - tag_name: models.CharField = models.CharField(max_length=400, null=True, blank=True) + tag_name = models.CharField(max_length=400, null=True, blank=True) diff --git a/posthog/models/activity_logging/activity_log.py b/posthog/models/activity_logging/activity_log.py index 1fb332e2e9e5f..5b3bec4ad7536 100644 --- a/posthog/models/activity_logging/activity_log.py +++ b/posthog/models/activity_logging/activity_log.py @@ -129,7 +129,7 @@ class Meta: # e.g. FeatureFlags - this will often be the name of a model class scope = models.fields.CharField(max_length=79, null=False) detail = models.JSONField(encoder=ActivityDetailEncoder, null=True) - created_at: models.DateTimeField = models.DateTimeField(default=timezone.now) + created_at = models.DateTimeField(default=timezone.now) common_field_exclusions = [ @@ -434,7 +434,8 @@ class ActivityPage: results: list[ActivityLog] -def get_activity_page(activity_query: models.QuerySet, limit: int = 10, page: int = 1) -> ActivityPage: +def get_activity_page(activity_query=10, page: int = 1) -> ActivityPage: + limit = 100 paginator = Paginator(activity_query, limit) activity_page = paginator.page(page) diff --git a/posthog/models/activity_logging/notification_viewed.py b/posthog/models/activity_logging/notification_viewed.py index cdecb69c1dbca..804e38de0f379 100644 --- a/posthog/models/activity_logging/notification_viewed.py +++ b/posthog/models/activity_logging/notification_viewed.py @@ -7,7 +7,7 @@ class NotificationViewed(UUIDModel): user = models.ForeignKey("posthog.User", null=True, on_delete=models.SET_NULL) # when viewing notifications made by viewing the activity log we count unread notifications # as any after the last viewed date - last_viewed_activity_date: models.DateTimeField = models.DateTimeField(default=None) + last_viewed_activity_date = models.DateTimeField(default=None) class Meta: constraints = [models.UniqueConstraint(fields=["user"], name="posthog_user_unique_viewed_date")] diff --git a/posthog/models/alert.py b/posthog/models/alert.py index 8aa62cf977b7a..973228820c752 100644 --- a/posthog/models/alert.py +++ b/posthog/models/alert.py @@ -12,9 +12,9 @@ def are_alerts_supported_for_insight(insight: Insight) -> bool: class Alert(models.Model): - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - insight: models.ForeignKey = models.ForeignKey("posthog.Insight", on_delete=models.CASCADE) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + insight = models.ForeignKey("posthog.Insight", on_delete=models.CASCADE) - name: models.CharField = models.CharField(max_length=100) - target_value: models.TextField = models.TextField() - anomaly_condition: models.JSONField = models.JSONField(default=dict) + name = models.CharField(max_length=100) + target_value = models.TextField() + anomaly_condition = models.JSONField(default=dict) diff --git a/posthog/models/annotation.py b/posthog/models/annotation.py index e99274f242c9e..c7301fba040f0 100644 --- a/posthog/models/annotation.py +++ b/posthog/models/annotation.py @@ -15,25 +15,21 @@ class CreationType(models.TextChoices): USER = "USR", "user" GITHUB = "GIT", "GitHub" - content: models.CharField = models.CharField(max_length=400, null=True, blank=True) - created_at: models.DateTimeField = models.DateTimeField(default=timezone.now, null=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) - dashboard_item: models.ForeignKey = models.ForeignKey( - "posthog.Insight", on_delete=models.SET_NULL, null=True, blank=True - ) - dashboard: models.ForeignKey = models.ForeignKey( - "posthog.Dashboard", on_delete=models.SET_NULL, null=True, blank=True - ) - team: models.ForeignKey = models.ForeignKey("posthog.Team", on_delete=models.CASCADE) - organization: models.ForeignKey = models.ForeignKey("posthog.Organization", on_delete=models.CASCADE, null=True) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) + content = models.CharField(max_length=400, null=True, blank=True) + created_at = models.DateTimeField(default=timezone.now, null=True) + updated_at = models.DateTimeField(auto_now=True) + dashboard_item = models.ForeignKey("posthog.Insight", on_delete=models.SET_NULL, null=True, blank=True) + dashboard = models.ForeignKey("posthog.Dashboard", on_delete=models.SET_NULL, null=True, blank=True) + team = models.ForeignKey("posthog.Team", on_delete=models.CASCADE) + organization = models.ForeignKey("posthog.Organization", on_delete=models.CASCADE, null=True) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) scope = models.CharField(max_length=24, choices=Scope.choices, default=Scope.INSIGHT) creation_type = models.CharField(max_length=3, choices=CreationType.choices, default=CreationType.USER) - date_marker: models.DateTimeField = models.DateTimeField(null=True, blank=True) - deleted: models.BooleanField = models.BooleanField(default=False) + date_marker = models.DateTimeField(null=True, blank=True) + deleted = models.BooleanField(default=False) # DEPRECATED: replaced by scope - apply_all: models.BooleanField = models.BooleanField(null=True) + apply_all = models.BooleanField(null=True) @property def insight_short_id(self) -> Optional[str]: diff --git a/posthog/models/async_deletion/async_deletion.py b/posthog/models/async_deletion/async_deletion.py index a851fa513f526..cb138d151128e 100644 --- a/posthog/models/async_deletion/async_deletion.py +++ b/posthog/models/async_deletion/async_deletion.py @@ -27,23 +27,21 @@ class Meta: ] indexes = [models.Index(name="delete_verified_at index", fields=["delete_verified_at"])] - id: models.BigAutoField = models.BigAutoField(primary_key=True) + id = models.BigAutoField(primary_key=True) # Should be one of the DeletionType enum - deletion_type: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField( - null=False, blank=False, choices=DeletionType.choices - ) + deletion_type = models.PositiveSmallIntegerField(null=False, blank=False, choices=DeletionType.choices) # Team whose data shall be deleted. This is not a foreign key, because we still need this value # when the team is gone (we are talking about _async_ deletions after all) - team_id: models.IntegerField = models.IntegerField() + team_id = models.IntegerField() # id for team (same as team_id column), uuid for person, key for group - key: models.CharField = models.CharField(max_length=400, null=False, blank=False) + key = models.CharField(max_length=400, null=False, blank=False) # Only populated for group deletions - group_type_index: models.IntegerField = models.IntegerField(null=True, blank=False) + group_type_index = models.IntegerField(null=True, blank=False) - created_by: models.ForeignKey = models.ForeignKey("User", null=True, on_delete=models.SET_NULL) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) + created_by = models.ForeignKey("User", null=True, on_delete=models.SET_NULL) + created_at = models.DateTimeField(auto_now_add=True) # When was the data verified to be deleted - we can skip it in the next round - delete_verified_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) + delete_verified_at = models.DateTimeField(null=True, blank=True) diff --git a/posthog/models/async_migration.py b/posthog/models/async_migration.py index 92d61fb5e3f33..c1d99e6a5825f 100644 --- a/posthog/models/async_migration.py +++ b/posthog/models/async_migration.py @@ -13,39 +13,35 @@ class MigrationStatus: class AsyncMigrationError(models.Model): - id: models.BigAutoField = models.BigAutoField(primary_key=True) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) - description: models.TextField = models.TextField(null=False, blank=False) - async_migration: models.ForeignKey = models.ForeignKey("AsyncMigration", on_delete=models.CASCADE) + id = models.BigAutoField(primary_key=True) + created_at = models.DateTimeField(auto_now_add=True, blank=True) + description = models.TextField(null=False, blank=False) + async_migration = models.ForeignKey("AsyncMigration", on_delete=models.CASCADE) class AsyncMigration(models.Model): class Meta: constraints = [models.UniqueConstraint(fields=["name"], name="unique name")] - id: models.BigAutoField = models.BigAutoField(primary_key=True) - name: models.CharField = models.CharField(max_length=50, null=False, blank=False) - description: models.CharField = models.CharField(max_length=400, null=True, blank=True) - progress: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField(null=False, blank=False, default=0) - status: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField( - null=False, blank=False, default=MigrationStatus.NotStarted - ) + id = models.BigAutoField(primary_key=True) + name = models.CharField(max_length=50, null=False, blank=False) + description = models.CharField(max_length=400, null=True, blank=True) + progress = models.PositiveSmallIntegerField(null=False, blank=False, default=0) + status = models.PositiveSmallIntegerField(null=False, blank=False, default=MigrationStatus.NotStarted) - current_operation_index: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField( - null=False, blank=False, default=0 - ) - current_query_id: models.CharField = models.CharField(max_length=100, null=False, blank=False, default="") - celery_task_id: models.CharField = models.CharField(max_length=100, null=False, blank=False, default="") + current_operation_index = models.PositiveSmallIntegerField(null=False, blank=False, default=0) + current_query_id = models.CharField(max_length=100, null=False, blank=False, default="") + celery_task_id = models.CharField(max_length=100, null=False, blank=False, default="") - started_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) + started_at = models.DateTimeField(null=True, blank=True) # Can finish with status 'CompletedSuccessfully', 'Errored', or 'RolledBack' - finished_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) + finished_at = models.DateTimeField(null=True, blank=True) - posthog_min_version: models.CharField = models.CharField(max_length=20, null=True, blank=True) - posthog_max_version: models.CharField = models.CharField(max_length=20, null=True, blank=True) + posthog_min_version = models.CharField(max_length=20, null=True, blank=True) + posthog_max_version = models.CharField(max_length=20, null=True, blank=True) - parameters: models.JSONField = models.JSONField(default=dict) + parameters = models.JSONField(default=dict) def get_name_with_requirements(self) -> str: return ( diff --git a/posthog/models/cohort/cohort.py b/posthog/models/cohort/cohort.py index 832178d6f4c7a..464de0cff9a3a 100644 --- a/posthog/models/cohort/cohort.py +++ b/posthog/models/cohort/cohort.py @@ -76,30 +76,30 @@ def create(self, *args: Any, **kwargs: Any): class Cohort(models.Model): - name: models.CharField = models.CharField(max_length=400, null=True, blank=True) - description: models.CharField = models.CharField(max_length=1000, blank=True) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - deleted: models.BooleanField = models.BooleanField(default=False) - filters: models.JSONField = models.JSONField(null=True, blank=True) - query: models.JSONField = models.JSONField(null=True, blank=True) - people: models.ManyToManyField = models.ManyToManyField("Person", through="CohortPeople") - version: models.IntegerField = models.IntegerField(blank=True, null=True) - pending_version: models.IntegerField = models.IntegerField(blank=True, null=True) - count: models.IntegerField = models.IntegerField(blank=True, null=True) - - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, blank=True, null=True) - created_at: models.DateTimeField = models.DateTimeField(default=timezone.now, blank=True, null=True) - - is_calculating: models.BooleanField = models.BooleanField(default=False) - last_calculation: models.DateTimeField = models.DateTimeField(blank=True, null=True) - errors_calculating: models.IntegerField = models.IntegerField(default=0) - - is_static: models.BooleanField = models.BooleanField(default=False) + name = models.CharField(max_length=400, null=True, blank=True) + description = models.CharField(max_length=1000, blank=True) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + deleted = models.BooleanField(default=False) + filters = models.JSONField(null=True, blank=True) + query = models.JSONField(null=True, blank=True) + people = models.ManyToManyField("Person", through="CohortPeople") + version = models.IntegerField(blank=True, null=True) + pending_version = models.IntegerField(blank=True, null=True) + count = models.IntegerField(blank=True, null=True) + + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, blank=True, null=True) + created_at = models.DateTimeField(default=timezone.now, blank=True, null=True) + + is_calculating = models.BooleanField(default=False) + last_calculation = models.DateTimeField(blank=True, null=True) + errors_calculating = models.IntegerField(default=0) + + is_static = models.BooleanField(default=False) objects = CohortManager() # deprecated in favor of filters - groups: models.JSONField = models.JSONField(default=list) + groups = models.JSONField(default=list) def __str__(self): return self.name @@ -368,10 +368,10 @@ def get_and_update_pending_version(cohort: Cohort): class CohortPeople(models.Model): - id: models.BigAutoField = models.BigAutoField(primary_key=True) - cohort: models.ForeignKey = models.ForeignKey("Cohort", on_delete=models.CASCADE) - person: models.ForeignKey = models.ForeignKey("Person", on_delete=models.CASCADE) - version: models.IntegerField = models.IntegerField(blank=True, null=True) + id = models.BigAutoField(primary_key=True) + cohort = models.ForeignKey("Cohort", on_delete=models.CASCADE) + person = models.ForeignKey("Person", on_delete=models.CASCADE) + version = models.IntegerField(blank=True, null=True) class Meta: indexes = [models.Index(fields=["cohort_id", "person_id"])] diff --git a/posthog/models/comment.py b/posthog/models/comment.py index a1fff705c0632..11c8128ef5811 100644 --- a/posthog/models/comment.py +++ b/posthog/models/comment.py @@ -9,12 +9,12 @@ class Comment(UUIDModel): - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - content: models.TextField = models.TextField(blank=True, null=True) - version: models.IntegerField = models.IntegerField(default=0) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) - deleted: models.BooleanField = models.BooleanField(null=True, blank=True, default=False) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + content = models.TextField(blank=True, null=True) + version = models.IntegerField(default=0) + created_at = models.DateTimeField(auto_now_add=True, blank=True) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) + deleted = models.BooleanField(null=True, blank=True, default=False) # Loose relationship modelling to other PostHog resources item_id = models.CharField(max_length=72, null=True) @@ -22,7 +22,7 @@ class Comment(UUIDModel): scope = models.CharField(max_length=79, null=False) # Threads/replies are simply comments with a source_comment_id - source_comment: models.ForeignKey = models.ForeignKey("Comment", on_delete=models.CASCADE, null=True, blank=True) + source_comment = models.ForeignKey("Comment", on_delete=models.CASCADE, null=True, blank=True) class Meta: indexes = [models.Index(fields=["team_id", "scope", "item_id"])] diff --git a/posthog/models/dashboard.py b/posthog/models/dashboard.py index f4fe641c004e2..ec46a5a309add 100644 --- a/posthog/models/dashboard.py +++ b/posthog/models/dashboard.py @@ -40,17 +40,17 @@ class PrivilegeLevel(models.IntegerChoices): CAN_VIEW = 21, "Can view dashboard" CAN_EDIT = 37, "Can edit dashboard" - name: models.CharField = models.CharField(max_length=400, null=True, blank=True) - description: models.TextField = models.TextField(blank=True) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - pinned: models.BooleanField = models.BooleanField(default=False) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) - deleted: models.BooleanField = models.BooleanField(default=False) - last_accessed_at: models.DateTimeField = models.DateTimeField(blank=True, null=True) - filters: models.JSONField = models.JSONField(default=dict) - creation_mode: models.CharField = models.CharField(max_length=16, default="default", choices=CreationMode.choices) - restriction_level: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField( + name = models.CharField(max_length=400, null=True, blank=True) + description = models.TextField(blank=True) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + pinned = models.BooleanField(default=False) + created_at = models.DateTimeField(auto_now_add=True, blank=True) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) + deleted = models.BooleanField(default=False) + last_accessed_at = models.DateTimeField(blank=True, null=True) + filters = models.JSONField(default=dict) + creation_mode = models.CharField(max_length=16, default="default", choices=CreationMode.choices) + restriction_level = models.PositiveSmallIntegerField( default=RestrictionLevel.EVERYONE_IN_PROJECT_CAN_EDIT, choices=RestrictionLevel.choices, ) @@ -72,12 +72,12 @@ class PrivilegeLevel(models.IntegerChoices): ) # DEPRECATED: using the new "sharing" relation instead - share_token: models.CharField = models.CharField(max_length=400, null=True, blank=True) + share_token = models.CharField(max_length=400, null=True, blank=True) # DEPRECATED: using the new "is_sharing_enabled" relation instead - is_shared: models.BooleanField = models.BooleanField(default=False) + is_shared = models.BooleanField(default=False) objects = DashboardManager() - objects_including_soft_deleted: models.Manager["Dashboard"] = models.Manager() + objects_including_soft_deleted = models.Manager() __repr__ = sane_repr("team_id", "id", "name") diff --git a/posthog/models/dashboard_templates.py b/posthog/models/dashboard_templates.py index 3d2c4a7678597..bf9d6dc733eb2 100644 --- a/posthog/models/dashboard_templates.py +++ b/posthog/models/dashboard_templates.py @@ -21,22 +21,22 @@ class Scope(models.TextChoices): GLOBAL = "global", "Global" FEATURE_FLAG = "feature_flag", "Feature Flag" - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE, null=True) - template_name: models.CharField = models.CharField(max_length=400, null=True, blank=True) - dashboard_description: models.CharField = models.CharField(max_length=400, null=True, blank=True) - dashboard_filters: models.JSONField = models.JSONField(null=True, blank=True) - tiles: models.JSONField = models.JSONField(blank=True, null=True) - variables: models.JSONField = models.JSONField(null=True, blank=True) + team = models.ForeignKey("Team", on_delete=models.CASCADE, null=True) + template_name = models.CharField(max_length=400, null=True, blank=True) + dashboard_description = models.CharField(max_length=400, null=True, blank=True) + dashboard_filters = models.JSONField(null=True, blank=True) + tiles = models.JSONField(blank=True, null=True) + variables = models.JSONField(null=True, blank=True) tags: ArrayField = ArrayField(models.CharField(max_length=255), blank=True, null=True) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True, null=True) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) - deleted: models.BooleanField = models.BooleanField(blank=True, null=True) - image_url: models.CharField = models.CharField(max_length=8201, null=True, blank=True) - scope: models.CharField = models.CharField(max_length=24, choices=Scope.choices, null=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) + deleted = models.BooleanField(blank=True, null=True) + image_url = models.CharField(max_length=8201, null=True, blank=True) + scope = models.CharField(max_length=24, choices=Scope.choices, null=True, blank=True) # URL length for browsers can be as much as 64Kb # see https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers # but GitHub apparently is more likely 8kb https://stackoverflow.com/a/64565317 - github_url: models.CharField = models.CharField(max_length=8201, null=True) + github_url = models.CharField(max_length=8201, null=True) class Meta: constraints = [ diff --git a/posthog/models/dashboard_tile.py b/posthog/models/dashboard_tile.py index b24fdf1989bb6..35454c2847c6a 100644 --- a/posthog/models/dashboard_tile.py +++ b/posthog/models/dashboard_tile.py @@ -9,11 +9,11 @@ class Text(models.Model): - body: models.CharField = models.CharField(max_length=4000, null=True, blank=True) + body = models.CharField(max_length=4000, null=True, blank=True) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) - last_modified_at: models.DateTimeField = models.DateTimeField(default=timezone.now) - last_modified_by: models.ForeignKey = models.ForeignKey( + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) + last_modified_at = models.DateTimeField(default=timezone.now) + last_modified_by = models.ForeignKey( "User", on_delete=models.SET_NULL, null=True, @@ -21,7 +21,7 @@ class Text(models.Model): related_name="modified_text_tiles", ) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) + team = models.ForeignKey("Team", on_delete=models.CASCADE) class DashboardTileManager(models.Manager): @@ -46,19 +46,19 @@ class DashboardTile(models.Model): ) # Tile layout and style - layouts: models.JSONField = models.JSONField(default=dict) - color: models.CharField = models.CharField(max_length=400, null=True, blank=True) + layouts = models.JSONField(default=dict) + color = models.CharField(max_length=400, null=True, blank=True) # caching for this dashboard & insight filter combination - filters_hash: models.CharField = models.CharField(max_length=400, null=True, blank=True) - last_refresh: models.DateTimeField = models.DateTimeField(blank=True, null=True) - refreshing: models.BooleanField = models.BooleanField(null=True) - refresh_attempt: models.IntegerField = models.IntegerField(null=True, blank=True) + filters_hash = models.CharField(max_length=400, null=True, blank=True) + last_refresh = models.DateTimeField(blank=True, null=True) + refreshing = models.BooleanField(null=True) + refresh_attempt = models.IntegerField(null=True, blank=True) - deleted: models.BooleanField = models.BooleanField(null=True, blank=True) + deleted = models.BooleanField(null=True, blank=True) objects = DashboardTileManager() - objects_including_soft_deleted: models.Manager["DashboardTile"] = models.Manager() + objects_including_soft_deleted = models.Manager() class Meta: indexes = [models.Index(fields=["filters_hash"], name="query_by_filters_hash_idx")] diff --git a/posthog/models/early_access_feature.py b/posthog/models/early_access_feature.py index 3ec1c99543b9a..453e184c7e18b 100644 --- a/posthog/models/early_access_feature.py +++ b/posthog/models/early_access_feature.py @@ -11,13 +11,13 @@ class Stage(models.TextChoices): GENERAL_AVAILABILITY = "general-availability", "general availability" ARCHIVED = "archived", "archived" - team: models.ForeignKey = models.ForeignKey( + team = models.ForeignKey( "posthog.Team", on_delete=models.CASCADE, related_name="features", related_query_name="feature", ) - feature_flag: models.ForeignKey = models.ForeignKey( + feature_flag = models.ForeignKey( "posthog.FeatureFlag", null=True, blank=True, @@ -25,11 +25,11 @@ class Stage(models.TextChoices): related_name="features", related_query_name="feature", ) - name: models.CharField = models.CharField(max_length=200) - description: models.TextField = models.TextField(blank=True) - stage: models.CharField = models.CharField(max_length=40, choices=Stage.choices) - documentation_url: models.URLField = models.URLField(max_length=800, blank=True) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) + name = models.CharField(max_length=200) + description = models.TextField(blank=True) + stage = models.CharField(max_length=40, choices=Stage.choices) + documentation_url = models.URLField(max_length=800, blank=True) + created_at = models.DateTimeField(auto_now_add=True) def __str__(self) -> str: return self.name diff --git a/posthog/models/element/element.py b/posthog/models/element/element.py index 4beeb5400851b..4727a7f9592ae 100644 --- a/posthog/models/element/element.py +++ b/posthog/models/element/element.py @@ -6,17 +6,17 @@ class Element(models.Model): USEFUL_ELEMENTS = ["a", "button", "input", "select", "textarea", "label"] - text: models.CharField = models.CharField(max_length=10_000, null=True, blank=True) - tag_name: models.CharField = models.CharField(max_length=1_000, null=True, blank=True) - href: models.CharField = models.CharField(max_length=10_000, null=True, blank=True) - attr_id: models.CharField = models.CharField(max_length=10_000, null=True, blank=True) + text = models.CharField(max_length=10_000, null=True, blank=True) + tag_name = models.CharField(max_length=1_000, null=True, blank=True) + href = models.CharField(max_length=10_000, null=True, blank=True) + attr_id = models.CharField(max_length=10_000, null=True, blank=True) attr_class = ArrayField(models.CharField(max_length=200, blank=True), null=True, blank=True) - nth_child: models.IntegerField = models.IntegerField(null=True, blank=True) - nth_of_type: models.IntegerField = models.IntegerField(null=True, blank=True) - attributes: models.JSONField = models.JSONField(default=dict) - event: models.ForeignKey = models.ForeignKey("Event", on_delete=models.CASCADE, null=True, blank=True) - order: models.IntegerField = models.IntegerField(null=True, blank=True) - group: models.ForeignKey = models.ForeignKey("ElementGroup", on_delete=models.CASCADE, null=True, blank=True) + nth_child = models.IntegerField(null=True, blank=True) + nth_of_type = models.IntegerField(null=True, blank=True) + attributes = models.JSONField(default=dict) + event = models.ForeignKey("Event", on_delete=models.CASCADE, null=True, blank=True) + order = models.IntegerField(null=True, blank=True) + group = models.ForeignKey("ElementGroup", on_delete=models.CASCADE, null=True, blank=True) parse_attributes_regex = re.compile(r"(?P(?P.*?)\=\"(?P.*?[^\\])\")", re.MULTILINE) diff --git a/posthog/models/element_group.py b/posthog/models/element_group.py index c4571180c4ecb..50de954ed1a9e 100644 --- a/posthog/models/element_group.py +++ b/posthog/models/element_group.py @@ -41,8 +41,8 @@ def create(self, *args: Any, **kwargs: Any): class ElementGroup(models.Model): - team: models.ForeignKey = models.ForeignKey(Team, on_delete=models.CASCADE) - hash: models.CharField = models.CharField(max_length=400, null=True, blank=True) + team = models.ForeignKey(Team, on_delete=models.CASCADE) + hash = models.CharField(max_length=400, null=True, blank=True) objects = ElementGroupManager() diff --git a/posthog/models/error_tracking/error_tracking.py b/posthog/models/error_tracking/error_tracking.py index ee7c0bfe3cb1e..1007e12699863 100644 --- a/posthog/models/error_tracking/error_tracking.py +++ b/posthog/models/error_tracking/error_tracking.py @@ -12,8 +12,8 @@ class Status(models.TextChoices): RESOLVED = "resolved", "Resolved" PENDING_RELEASE = "pending_release", "Pending release" - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + created_at = models.DateTimeField(auto_now_add=True, blank=True) fingerprint: ArrayField = ArrayField(models.TextField(null=False, blank=False), null=False, blank=False) merged_fingerprints: ArrayField = ArrayField( ArrayField(models.TextField(null=False, blank=False), null=False, blank=False), @@ -21,10 +21,8 @@ class Status(models.TextChoices): blank=False, default=list, ) - status: models.CharField = models.CharField( - max_length=40, choices=Status.choices, default=Status.ACTIVE, null=False - ) - assignee: models.ForeignKey = models.ForeignKey( + status = models.CharField(max_length=40, choices=Status.choices, default=Status.ACTIVE, null=False) + assignee = models.ForeignKey( "User", on_delete=models.SET_NULL, null=True, diff --git a/posthog/models/event/event.py b/posthog/models/event/event.py index 184fffb18afa6..3c3fd2100dda9 100644 --- a/posthog/models/event/event.py +++ b/posthog/models/event/event.py @@ -133,14 +133,14 @@ class Meta: # models.Index(fields=["distinct_id"], name="idx_distinct_id"), ] - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, null=True, blank=True) - team: models.ForeignKey = models.ForeignKey(Team, on_delete=models.CASCADE) - event: models.CharField = models.CharField(max_length=200, null=True, blank=True) - distinct_id: models.CharField = models.CharField(max_length=200) - properties: models.JSONField = models.JSONField(default=dict) - timestamp: models.DateTimeField = models.DateTimeField(default=timezone.now, blank=True) - elements_hash: models.CharField = models.CharField(max_length=200, null=True, blank=True) - site_url: models.CharField = models.CharField(max_length=200, null=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True) + team = models.ForeignKey(Team, on_delete=models.CASCADE) + event = models.CharField(max_length=200, null=True, blank=True) + distinct_id = models.CharField(max_length=200) + properties = models.JSONField(default=dict) + timestamp = models.DateTimeField(default=timezone.now, blank=True) + elements_hash = models.CharField(max_length=200, null=True, blank=True) + site_url = models.CharField(max_length=200, null=True, blank=True) # DEPRECATED: elements are stored against element groups now - elements: models.JSONField = models.JSONField(default=list, null=True, blank=True) + elements = models.JSONField(default=list, null=True, blank=True) diff --git a/posthog/models/event_buffer.py b/posthog/models/event_buffer.py index f8cfed80775cd..b52d957a3f396 100644 --- a/posthog/models/event_buffer.py +++ b/posthog/models/event_buffer.py @@ -2,6 +2,6 @@ class EventBuffer(models.Model): - event: models.JSONField = models.JSONField(null=True, blank=True) - process_at: models.DateTimeField = models.DateTimeField() - locked: models.BooleanField = models.BooleanField() + event = models.JSONField(null=True, blank=True) + process_at = models.DateTimeField() + locked = models.BooleanField() diff --git a/posthog/models/event_definition.py b/posthog/models/event_definition.py index 5b22a9e6a2869..3f5c8d8a6f45b 100644 --- a/posthog/models/event_definition.py +++ b/posthog/models/event_definition.py @@ -7,23 +7,23 @@ class EventDefinition(UUIDModel): - team: models.ForeignKey = models.ForeignKey( + team = models.ForeignKey( Team, on_delete=models.CASCADE, related_name="event_definitions", related_query_name="team", ) - name: models.CharField = models.CharField(max_length=400) - created_at: models.DateTimeField = models.DateTimeField(default=timezone.now, null=True) - last_seen_at: models.DateTimeField = models.DateTimeField(default=None, null=True) + name = models.CharField(max_length=400) + created_at = models.DateTimeField(default=timezone.now, null=True) + last_seen_at = models.DateTimeField(default=None, null=True) # DEPRECATED # Number of times the event has been used in a query in the last 30 rolling days (computed asynchronously every other blue moon) - query_usage_30_day: models.IntegerField = models.IntegerField(default=None, null=True) + query_usage_30_day = models.IntegerField(default=None, null=True) # DEPRECATED # Volume of events in the last 30 rolling days (computed asynchronously) - volume_30_day: models.IntegerField = models.IntegerField(default=None, null=True) + volume_30_day = models.IntegerField(default=None, null=True) class Meta: unique_together = ("team", "name") diff --git a/posthog/models/event_property.py b/posthog/models/event_property.py index 4824248ddfce2..a5087c5b3f667 100644 --- a/posthog/models/event_property.py +++ b/posthog/models/event_property.py @@ -5,9 +5,9 @@ class EventProperty(models.Model): - team: models.ForeignKey = models.ForeignKey(Team, on_delete=models.CASCADE) - event: models.CharField = models.CharField(max_length=400, null=False) - property: models.CharField = models.CharField(max_length=400, null=False) + team = models.ForeignKey(Team, on_delete=models.CASCADE) + event = models.CharField(max_length=400, null=False) + property = models.CharField(max_length=400, null=False) class Meta: constraints = [ diff --git a/posthog/models/experiment.py b/posthog/models/experiment.py index d20e59a96b3d0..9534c2a28914f 100644 --- a/posthog/models/experiment.py +++ b/posthog/models/experiment.py @@ -3,12 +3,12 @@ class Experiment(models.Model): - name: models.CharField = models.CharField(max_length=400) - description: models.CharField = models.CharField(max_length=400, null=True, blank=True) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) + name = models.CharField(max_length=400) + description = models.CharField(max_length=400, null=True, blank=True) + team = models.ForeignKey("Team", on_delete=models.CASCADE) # Filters define the target metric of an Experiment - filters: models.JSONField = models.JSONField(default=dict) + filters = models.JSONField(default=dict) # Parameters include configuration fields for the experiment: What the control & test variant are called, # and any test significance calculation parameters @@ -18,19 +18,19 @@ class Experiment(models.Model): # recommended_sample_size: number # feature_flag_variants: { key: string, name: string, rollout_percentage: number }[] # custom_exposure_filter: Filter json - parameters: models.JSONField = models.JSONField(default=dict, null=True) + parameters = models.JSONField(default=dict, null=True) # A list of filters for secondary metrics - secondary_metrics: models.JSONField = models.JSONField(default=list, null=True) - - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True) - feature_flag: models.ForeignKey = models.ForeignKey("FeatureFlag", blank=False, on_delete=models.RESTRICT) - exposure_cohort: models.ForeignKey = models.ForeignKey("Cohort", on_delete=models.SET_NULL, null=True) - start_date: models.DateTimeField = models.DateTimeField(null=True) - end_date: models.DateTimeField = models.DateTimeField(null=True) - created_at: models.DateTimeField = models.DateTimeField(default=timezone.now) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) - archived: models.BooleanField = models.BooleanField(default=False) + secondary_metrics = models.JSONField(default=list, null=True) + + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True) + feature_flag = models.ForeignKey("FeatureFlag", blank=False, on_delete=models.RESTRICT) + exposure_cohort = models.ForeignKey("Cohort", on_delete=models.SET_NULL, null=True) + start_date = models.DateTimeField(null=True) + end_date = models.DateTimeField(null=True) + created_at = models.DateTimeField(default=timezone.now) + updated_at = models.DateTimeField(auto_now=True) + archived = models.BooleanField(default=False) def get_feature_flag_key(self): return self.feature_flag.key diff --git a/posthog/models/exported_asset.py b/posthog/models/exported_asset.py index 7d4746234aba5..8b5be56e67d3d 100644 --- a/posthog/models/exported_asset.py +++ b/posthog/models/exported_asset.py @@ -48,34 +48,32 @@ class ExportFormat(models.TextChoices): SUPPORTED_FORMATS = [ExportFormat.PNG, ExportFormat.CSV, ExportFormat.XLSX] # Relations - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) + team = models.ForeignKey("Team", on_delete=models.CASCADE) dashboard = models.ForeignKey("posthog.Dashboard", on_delete=models.CASCADE, null=True) insight = models.ForeignKey("posthog.Insight", on_delete=models.CASCADE, null=True) # Content related fields - export_format: models.CharField = models.CharField(max_length=100, choices=ExportFormat.choices) - content: models.BinaryField = models.BinaryField(null=True) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) + export_format = models.CharField(max_length=100, choices=ExportFormat.choices) + content = models.BinaryField(null=True) + created_at = models.DateTimeField(auto_now_add=True, blank=True) # DateTime after the created_at after which this asset should be deleted # ExportedAssets are *not* deleted immediately after the TTL period has passed # the object manager has been altered to exclude these assets # to allow for lazy deletes - expires_after: models.DateTimeField = models.DateTimeField(null=True, blank=True) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) + expires_after = models.DateTimeField(null=True, blank=True) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) # for example holds filters for CSV exports - export_context: models.JSONField = models.JSONField(null=True, blank=True) + export_context = models.JSONField(null=True, blank=True) # path in object storage or some other location identifier for the asset # 1000 characters would hold a 20 UUID forward slash separated path with space to spare - content_location: models.TextField = models.TextField(null=True, blank=True, max_length=1000) + content_location = models.TextField(null=True, blank=True, max_length=1000) # DEPRECATED: We now use JWT for accessing assets - access_token: models.CharField = models.CharField( - max_length=400, null=True, blank=True, default=get_default_access_token - ) + access_token = models.CharField(max_length=400, null=True, blank=True, default=get_default_access_token) # replace the default manager with one that filters out TTL deleted objects (before their deletion is processed) objects = ExportedAssetManager() - objects_including_ttl_deleted: models.Manager["ExportedAsset"] = models.Manager() + objects_including_ttl_deleted = models.Manager() @property def has_content(self): diff --git a/posthog/models/feature_flag/feature_flag.py b/posthog/models/feature_flag/feature_flag.py index ff9f091957066..5ac39d59f7ff6 100644 --- a/posthog/models/feature_flag/feature_flag.py +++ b/posthog/models/feature_flag/feature_flag.py @@ -29,35 +29,33 @@ class Meta: constraints = [models.UniqueConstraint(fields=["team", "key"], name="unique key for team")] # When adding new fields, make sure to update organization_feature_flags.py::copy_flags - key: models.CharField = models.CharField(max_length=400) - name: models.TextField = models.TextField( + key = models.CharField(max_length=400) + name = models.TextField( blank=True ) # contains description for the FF (field name `name` is kept for backwards-compatibility) - filters: models.JSONField = models.JSONField(default=dict) - rollout_percentage: models.IntegerField = models.IntegerField(null=True, blank=True) + filters = models.JSONField(default=dict) + rollout_percentage = models.IntegerField(null=True, blank=True) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True) - created_at: models.DateTimeField = models.DateTimeField(default=timezone.now) - deleted: models.BooleanField = models.BooleanField(default=False) - active: models.BooleanField = models.BooleanField(default=True) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True) + created_at = models.DateTimeField(default=timezone.now) + deleted = models.BooleanField(default=False) + active = models.BooleanField(default=True) - rollback_conditions: models.JSONField = models.JSONField(null=True, blank=True) - performed_rollback: models.BooleanField = models.BooleanField(null=True, blank=True) + rollback_conditions = models.JSONField(null=True, blank=True) + performed_rollback = models.BooleanField(null=True, blank=True) - ensure_experience_continuity: models.BooleanField = models.BooleanField(default=False, null=True, blank=True) - usage_dashboard: models.ForeignKey = models.ForeignKey( - "Dashboard", on_delete=models.SET_NULL, null=True, blank=True - ) - analytics_dashboards: models.ManyToManyField = models.ManyToManyField( + ensure_experience_continuity = models.BooleanField(default=False, null=True, blank=True) + usage_dashboard = models.ForeignKey("Dashboard", on_delete=models.SET_NULL, null=True, blank=True) + analytics_dashboards = models.ManyToManyField( "Dashboard", through="FeatureFlagDashboards", related_name="analytics_dashboards", related_query_name="analytics_dashboard", ) # whether a feature is sending us rich analytics, like views & interactions. - has_enriched_analytics: models.BooleanField = models.BooleanField(default=False, null=True, blank=True) + has_enriched_analytics = models.BooleanField(default=False, null=True, blank=True) def __str__(self): return f"{self.key} ({self.pk})" @@ -374,10 +372,10 @@ class Meta: # the unique constraint is on (team_id+key), and not just key. # A standard id foreign key leads to INNER JOINs every time we want to get the key # and we only ever want to get the key. - feature_flag_key: models.CharField = models.CharField(max_length=400) - person: models.ForeignKey = models.ForeignKey("Person", on_delete=models.CASCADE) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - hash_key: models.CharField = models.CharField(max_length=400) + feature_flag_key = models.CharField(max_length=400) + person = models.ForeignKey("Person", on_delete=models.CASCADE) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + hash_key = models.CharField(max_length=400) # DEPRECATED: This model is no longer used, but it's not deleted to avoid downtime @@ -390,10 +388,10 @@ class Meta: ) ] - feature_flag: models.ForeignKey = models.ForeignKey("FeatureFlag", on_delete=models.CASCADE) - user: models.ForeignKey = models.ForeignKey("User", on_delete=models.CASCADE) - override_value: models.JSONField = models.JSONField() - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) + feature_flag = models.ForeignKey("FeatureFlag", on_delete=models.CASCADE) + user = models.ForeignKey("User", on_delete=models.CASCADE) + override_value = models.JSONField() + team = models.ForeignKey("Team", on_delete=models.CASCADE) def set_feature_flags_for_team_in_cache( @@ -443,10 +441,10 @@ def get_feature_flags_for_team_in_cache(team_id: int) -> Optional[list[FeatureFl class FeatureFlagDashboards(models.Model): - feature_flag: models.ForeignKey = models.ForeignKey("FeatureFlag", on_delete=models.CASCADE) - dashboard: models.ForeignKey = models.ForeignKey("Dashboard", on_delete=models.CASCADE) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, null=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True, null=True) + feature_flag = models.ForeignKey("FeatureFlag", on_delete=models.CASCADE) + dashboard = models.ForeignKey("Dashboard", on_delete=models.CASCADE) + created_at = models.DateTimeField(auto_now_add=True, null=True) + updated_at = models.DateTimeField(auto_now=True, null=True) class Meta: constraints = [ diff --git a/posthog/models/feedback/survey.py b/posthog/models/feedback/survey.py index d7d2008868c90..064206e6e92d9 100644 --- a/posthog/models/feedback/survey.py +++ b/posthog/models/feedback/survey.py @@ -22,15 +22,15 @@ class SurveyType(models.TextChoices): class Meta: constraints = [models.UniqueConstraint(fields=["team", "name"], name="unique survey name for team")] - team: models.ForeignKey = models.ForeignKey( + team = models.ForeignKey( "posthog.Team", on_delete=models.CASCADE, related_name="surveys", related_query_name="survey", ) - name: models.CharField = models.CharField(max_length=400) - description: models.TextField = models.TextField(blank=True) - linked_flag: models.ForeignKey = models.ForeignKey( + name = models.CharField(max_length=400) + description = models.TextField(blank=True) + linked_flag = models.ForeignKey( "posthog.FeatureFlag", null=True, blank=True, @@ -38,7 +38,7 @@ class Meta: related_name="surveys_linked_flag", related_query_name="survey_linked_flag", ) - targeting_flag: models.ForeignKey = models.ForeignKey( + targeting_flag = models.ForeignKey( "posthog.FeatureFlag", null=True, blank=True, @@ -46,7 +46,7 @@ class Meta: related_name="surveys_targeting_flag", related_query_name="survey_targeting_flag", ) - internal_targeting_flag: models.ForeignKey = models.ForeignKey( + internal_targeting_flag = models.ForeignKey( "posthog.FeatureFlag", null=True, blank=True, @@ -54,9 +54,9 @@ class Meta: related_name="surveys_internal_targeting_flag", related_query_name="survey_internal_targeting_flag", ) - type: models.CharField = models.CharField(max_length=40, choices=SurveyType.choices) - conditions: models.JSONField = models.JSONField(blank=True, null=True) - questions: models.JSONField = models.JSONField( + type = models.CharField(max_length=40, choices=SurveyType.choices) + conditions = models.JSONField(blank=True, null=True) + questions = models.JSONField( blank=True, null=True, help_text=""" @@ -141,19 +141,19 @@ class Meta: ``` """, ) - appearance: models.JSONField = models.JSONField(blank=True, null=True) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - created_by: models.ForeignKey = models.ForeignKey( + appearance = models.JSONField(blank=True, null=True) + created_at = models.DateTimeField(auto_now_add=True) + created_by = models.ForeignKey( "posthog.User", on_delete=models.SET_NULL, related_name="surveys", related_query_name="survey", null=True, ) - start_date: models.DateTimeField = models.DateTimeField(null=True) - end_date: models.DateTimeField = models.DateTimeField(null=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) - archived: models.BooleanField = models.BooleanField(default=False) + start_date = models.DateTimeField(null=True) + end_date = models.DateTimeField(null=True) + updated_at = models.DateTimeField(auto_now=True) + archived = models.BooleanField(default=False) # It's not a strict limit as it's enforced in a periodic task responses_limit = models.PositiveIntegerField(null=True) diff --git a/posthog/models/group/group.py b/posthog/models/group/group.py index f07f4229988ba..455789bdd769d 100644 --- a/posthog/models/group/group.py +++ b/posthog/models/group/group.py @@ -10,18 +10,18 @@ class Meta: ) ] - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - group_key: models.CharField = models.CharField(max_length=400, null=False, blank=False) - group_type_index: models.IntegerField = models.IntegerField(null=False, blank=False) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + group_key = models.CharField(max_length=400, null=False, blank=False) + group_type_index = models.IntegerField(null=False, blank=False) - group_properties: models.JSONField = models.JSONField(default=dict) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) + group_properties = models.JSONField(default=dict) + created_at = models.DateTimeField(auto_now_add=True) # used to prevent race conditions with set and set_once - properties_last_updated_at: models.JSONField = models.JSONField(default=dict) + properties_last_updated_at = models.JSONField(default=dict) # used for evaluating if we need to override the value or not (value: set or set_once) - properties_last_operation: models.JSONField = models.JSONField(default=dict) + properties_last_operation = models.JSONField(default=dict) # current version of the group, used to sync with ClickHouse and collapse rows correctly - version: models.BigIntegerField = models.BigIntegerField(null=False) + version = models.BigIntegerField(null=False) diff --git a/posthog/models/group_type_mapping.py b/posthog/models/group_type_mapping.py index ed4a19164f4fb..c9bae789b9d6c 100644 --- a/posthog/models/group_type_mapping.py +++ b/posthog/models/group_type_mapping.py @@ -17,9 +17,9 @@ class Meta: ), ] - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - group_type: models.CharField = models.CharField(max_length=400, null=False, blank=False) - group_type_index: models.IntegerField = models.IntegerField(null=False, blank=False) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + group_type = models.CharField(max_length=400, null=False, blank=False) + group_type_index = models.IntegerField(null=False, blank=False) # Used to display in UI - name_singular: models.CharField = models.CharField(max_length=400, null=True, blank=True) - name_plural: models.CharField = models.CharField(max_length=400, null=True, blank=True) + name_singular = models.CharField(max_length=400, null=True, blank=True) + name_plural = models.CharField(max_length=400, null=True, blank=True) diff --git a/posthog/models/hog_functions/hog_function.py b/posthog/models/hog_functions/hog_function.py index ca6bb1f236105..529e822c86fd2 100644 --- a/posthog/models/hog_functions/hog_function.py +++ b/posthog/models/hog_functions/hog_function.py @@ -31,23 +31,23 @@ class HogFunctionState(enum.Enum): class HogFunction(UUIDModel): - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - name: models.CharField = models.CharField(max_length=400, null=True, blank=True) - description: models.TextField = models.TextField(blank=True, default="") - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) - deleted: models.BooleanField = models.BooleanField(default=False) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) - enabled: models.BooleanField = models.BooleanField(default=False) - - icon_url: models.TextField = models.TextField(null=True, blank=True) - hog: models.TextField = models.TextField() - bytecode: models.JSONField = models.JSONField(null=True, blank=True) - inputs_schema: models.JSONField = models.JSONField(null=True) - inputs: models.JSONField = models.JSONField(null=True) - filters: models.JSONField = models.JSONField(null=True, blank=True) - masking: models.JSONField = models.JSONField(null=True, blank=True) - template_id: models.CharField = models.CharField(max_length=400, null=True, blank=True) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + name = models.CharField(max_length=400, null=True, blank=True) + description = models.TextField(blank=True, default="") + created_at = models.DateTimeField(auto_now_add=True, blank=True) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) + deleted = models.BooleanField(default=False) + updated_at = models.DateTimeField(auto_now=True) + enabled = models.BooleanField(default=False) + + icon_url = models.TextField(null=True, blank=True) + hog = models.TextField() + bytecode = models.JSONField(null=True, blank=True) + inputs_schema = models.JSONField(null=True) + inputs = models.JSONField(null=True) + filters = models.JSONField(null=True, blank=True) + masking = models.JSONField(null=True, blank=True) + template_id = models.CharField(max_length=400, null=True, blank=True) @property def template(self) -> Optional[HogFunctionTemplate]: diff --git a/posthog/models/insight.py b/posthog/models/insight.py index 2fcb7213dd618..704b61b931d2d 100644 --- a/posthog/models/insight.py +++ b/posthog/models/insight.py @@ -29,27 +29,27 @@ class Insight(models.Model): reports or part of a dashboard. """ - name: models.CharField = models.CharField(max_length=400, null=True, blank=True) - derived_name: models.CharField = models.CharField(max_length=400, null=True, blank=True) - description: models.CharField = models.CharField(max_length=400, null=True, blank=True) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - filters: models.JSONField = models.JSONField(default=dict) - filters_hash: models.CharField = models.CharField(max_length=400, null=True, blank=True) - query: models.JSONField = models.JSONField(null=True, blank=True) - order: models.IntegerField = models.IntegerField(null=True, blank=True) - deleted: models.BooleanField = models.BooleanField(default=False) - saved: models.BooleanField = models.BooleanField(default=False) - created_at: models.DateTimeField = models.DateTimeField(null=True, blank=True, auto_now_add=True) - refreshing: models.BooleanField = models.BooleanField(default=False) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) + name = models.CharField(max_length=400, null=True, blank=True) + derived_name = models.CharField(max_length=400, null=True, blank=True) + description = models.CharField(max_length=400, null=True, blank=True) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + filters = models.JSONField(default=dict) + filters_hash = models.CharField(max_length=400, null=True, blank=True) + query = models.JSONField(null=True, blank=True) + order = models.IntegerField(null=True, blank=True) + deleted = models.BooleanField(default=False) + saved = models.BooleanField(default=False) + created_at = models.DateTimeField(null=True, blank=True, auto_now_add=True) + refreshing = models.BooleanField(default=False) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) # Indicates if it's a sample graph generated by dashboard templates - is_sample: models.BooleanField = models.BooleanField(default=False) + is_sample = models.BooleanField(default=False) # Unique ID per team for easy sharing and short links - short_id: models.CharField = models.CharField(max_length=12, blank=True, default=generate_short_id) - favorited: models.BooleanField = models.BooleanField(default=False) - refresh_attempt: models.IntegerField = models.IntegerField(null=True, blank=True) - last_modified_at: models.DateTimeField = models.DateTimeField(default=timezone.now) - last_modified_by: models.ForeignKey = models.ForeignKey( + short_id = models.CharField(max_length=12, blank=True, default=generate_short_id) + favorited = models.BooleanField(default=False) + refresh_attempt = models.IntegerField(null=True, blank=True) + last_modified_at = models.DateTimeField(default=timezone.now) + last_modified_by = models.ForeignKey( "User", on_delete=models.SET_NULL, null=True, @@ -58,7 +58,7 @@ class Insight(models.Model): ) # DEPRECATED: using the new "dashboards" relation instead - dashboard: models.ForeignKey = models.ForeignKey( + dashboard = models.ForeignKey( "Dashboard", related_name="items", on_delete=models.CASCADE, @@ -66,19 +66,19 @@ class Insight(models.Model): blank=True, ) # DEPRECATED: within cached results package now - last_refresh: models.DateTimeField = models.DateTimeField(blank=True, null=True) + last_refresh = models.DateTimeField(blank=True, null=True) # DEPRECATED: on dashboard_insight now - layouts: models.JSONField = models.JSONField(default=dict) + layouts = models.JSONField(default=dict) # DEPRECATED: on dashboard_insight now - color: models.CharField = models.CharField(max_length=400, null=True, blank=True) + color = models.CharField(max_length=400, null=True, blank=True) # DEPRECATED: dive dashboards were never shipped - dive_dashboard: models.ForeignKey = models.ForeignKey("Dashboard", on_delete=models.SET_NULL, null=True, blank=True) + dive_dashboard = models.ForeignKey("Dashboard", on_delete=models.SET_NULL, null=True, blank=True) # DEPRECATED: in practically all cases field `last_modified_at` should be used instead - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) + updated_at = models.DateTimeField(auto_now=True) # DEPRECATED: use `display` property of the Filter object instead - type: models.CharField = deprecate_field(models.CharField(max_length=400, null=True, blank=True)) + type = deprecate_field(models.CharField(max_length=400, null=True, blank=True)) # DEPRECATED: we don't store funnels as a separate model any more - funnel: models.IntegerField = deprecate_field(models.IntegerField(null=True, blank=True)) + funnel = deprecate_field(models.IntegerField(null=True, blank=True)) # DEPRECATED: now using app-wide tagging model. See EnterpriseTaggedItem deprecated_tags: ArrayField = ArrayField(models.CharField(max_length=32), null=True, blank=True, default=list) # DEPRECATED: now using app-wide tagging model. See EnterpriseTaggedItem @@ -96,7 +96,7 @@ class Insight(models.Model): __repr__ = sane_repr("team_id", "id", "short_id", "name") objects = InsightManager() - objects_including_soft_deleted: models.Manager["Insight"] = models.Manager() + objects_including_soft_deleted = models.Manager() class Meta: db_table = "posthog_dashboarditem" @@ -199,10 +199,10 @@ class Meta: constraints = [models.UniqueConstraint(fields=["team", "user", "insight"], name="posthog_unique_insightviewed")] indexes = [models.Index(fields=["team_id", "user_id", "-last_viewed_at"])] - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - user: models.ForeignKey = models.ForeignKey("User", on_delete=models.CASCADE) - insight: models.ForeignKey = models.ForeignKey(Insight, on_delete=models.CASCADE) - last_viewed_at: models.DateTimeField = models.DateTimeField() + team = models.ForeignKey("Team", on_delete=models.CASCADE) + user = models.ForeignKey("User", on_delete=models.CASCADE) + insight = models.ForeignKey(Insight, on_delete=models.CASCADE) + last_viewed_at = models.DateTimeField() @timed("generate_insight_cache_key") diff --git a/posthog/models/insight_caching_state.py b/posthog/models/insight_caching_state.py index 6ee767bc520e2..ab6c1c9d67d5b 100644 --- a/posthog/models/insight_caching_state.py +++ b/posthog/models/insight_caching_state.py @@ -21,7 +21,7 @@ class Meta: ) ] - team: models.ForeignKey = models.ForeignKey(Team, on_delete=models.CASCADE) + team = models.ForeignKey(Team, on_delete=models.CASCADE) insight = models.ForeignKey( "posthog.Insight", @@ -35,16 +35,16 @@ class Meta: related_name="caching_states", null=True, ) - cache_key: models.CharField = models.CharField(max_length=400, null=False, blank=False) + cache_key = models.CharField(max_length=400, null=False, blank=False) - target_cache_age_seconds: models.IntegerField = models.IntegerField(null=True) + target_cache_age_seconds = models.IntegerField(null=True) - last_refresh: models.DateTimeField = models.DateTimeField(blank=True, null=True) - last_refresh_queued_at: models.DateTimeField = models.DateTimeField(blank=True, null=True) - refresh_attempt: models.IntegerField = models.IntegerField(null=False, default=0) + last_refresh = models.DateTimeField(blank=True, null=True) + last_refresh_queued_at = models.DateTimeField(blank=True, null=True) + refresh_attempt = models.IntegerField(null=False, default=0) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) @mutable_receiver(post_save, sender=SharingConfiguration) diff --git a/posthog/models/instance_setting.py b/posthog/models/instance_setting.py index e03e72535c9ae..739c89bc80102 100644 --- a/posthog/models/instance_setting.py +++ b/posthog/models/instance_setting.py @@ -12,8 +12,8 @@ class InstanceSetting(models.Model): class Meta: constraints = [models.UniqueConstraint(fields=["key"], name="unique key")] - key: models.CharField = models.CharField(max_length=128, null=False, blank=False) - raw_value: models.CharField = models.CharField(max_length=1024, null=False, blank=True) + key = models.CharField(max_length=128, null=False, blank=False) + raw_value = models.CharField(max_length=1024, null=False, blank=True) @property def value(self): diff --git a/posthog/models/integration.py b/posthog/models/integration.py index 38cac084e200a..f6c6a27ccfd00 100644 --- a/posthog/models/integration.py +++ b/posthog/models/integration.py @@ -47,22 +47,22 @@ class Meta: ) ] - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) + team = models.ForeignKey("Team", on_delete=models.CASCADE) # The integration type identifier - kind: models.CharField = models.CharField(max_length=10, choices=IntegrationKind.choices) + kind = models.CharField(max_length=10, choices=IntegrationKind.choices) # The ID of the integration in the external system - integration_id: models.TextField = models.TextField(null=True, blank=True) + integration_id = models.TextField(null=True, blank=True) # Any config that COULD be passed to the frontend - config: models.JSONField = models.JSONField(default=dict) + config = models.JSONField(default=dict) # Any sensitive config that SHOULD NOT be passed to the frontend - sensitive_config: models.JSONField = models.JSONField(default=dict) + sensitive_config = models.JSONField(default=dict) - errors: models.TextField = models.TextField() + errors = models.TextField() # Meta - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True, blank=True) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) @property def display_name(self) -> str: diff --git a/posthog/models/messaging.py b/posthog/models/messaging.py index 5514f98baccb2..1f013ce09f75d 100644 --- a/posthog/models/messaging.py +++ b/posthog/models/messaging.py @@ -23,12 +23,12 @@ def get_or_create(self, defaults=None, **kwargs): class MessagingRecord(UUIDModel): objects = MessagingRecordManager() - email_hash: models.CharField = models.CharField(max_length=1024) - campaign_key: models.CharField = models.CharField(max_length=128) + email_hash = models.CharField(max_length=1024) + campaign_key = models.CharField(max_length=128) # Numeric indicator for repeat emails of the same campaign key - campaign_count: models.IntegerField = models.IntegerField(null=True) - sent_at: models.DateTimeField = models.DateTimeField(null=True) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) + campaign_count = models.IntegerField(null=True) + sent_at = models.DateTimeField(null=True) + created_at = models.DateTimeField(auto_now_add=True) class Meta: unique_together = ( diff --git a/posthog/models/notebook/notebook.py b/posthog/models/notebook/notebook.py index ec61ab1c22ed0..48553a684cb65 100644 --- a/posthog/models/notebook/notebook.py +++ b/posthog/models/notebook/notebook.py @@ -8,17 +8,17 @@ class Notebook(UUIDModel): - short_id: models.CharField = models.CharField(max_length=12, blank=True, default=generate_short_id) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - title: models.CharField = models.CharField(max_length=256, blank=True, null=True) + short_id = models.CharField(max_length=12, blank=True, default=generate_short_id) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + title = models.CharField(max_length=256, blank=True, null=True) content: JSONField = JSONField(default=None, null=True, blank=True) - text_content: models.TextField = models.TextField(blank=True, null=True) - deleted: models.BooleanField = models.BooleanField(default=False) - version: models.IntegerField = models.IntegerField(default=0) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) - last_modified_at: models.DateTimeField = models.DateTimeField(default=timezone.now) - last_modified_by: models.ForeignKey = models.ForeignKey( + text_content = models.TextField(blank=True, null=True) + deleted = models.BooleanField(default=False) + version = models.IntegerField(default=0) + created_at = models.DateTimeField(auto_now_add=True, blank=True) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) + last_modified_at = models.DateTimeField(default=timezone.now) + last_modified_by = models.ForeignKey( "User", on_delete=models.SET_NULL, null=True, diff --git a/posthog/models/organization.py b/posthog/models/organization.py index 5f146fc8b45a2..e64f45ff8abc4 100644 --- a/posthog/models/organization.py +++ b/posthog/models/organization.py @@ -112,31 +112,29 @@ class PluginsAccessLevel(models.IntegerChoices): # This includes installing plugins from the repository and managing plugin installations for all other orgs. ROOT = 9, "root" - members: models.ManyToManyField = models.ManyToManyField( + members = models.ManyToManyField( "posthog.User", through="posthog.OrganizationMembership", related_name="organizations", related_query_name="organization", ) - name: models.CharField = models.CharField(max_length=64) + name = models.CharField(max_length=64) slug: LowercaseSlugField = LowercaseSlugField(unique=True, max_length=MAX_SLUG_LENGTH) - logo_media: models.ForeignKey = models.ForeignKey( - "posthog.UploadedMedia", on_delete=models.SET_NULL, null=True, blank=True - ) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) - plugins_access_level: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField( + logo_media = models.ForeignKey("posthog.UploadedMedia", on_delete=models.SET_NULL, null=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + plugins_access_level = models.PositiveSmallIntegerField( default=PluginsAccessLevel.CONFIG, choices=PluginsAccessLevel.choices, ) - for_internal_metrics: models.BooleanField = models.BooleanField(default=False) - is_member_join_email_enabled: models.BooleanField = models.BooleanField(default=True) - enforce_2fa: models.BooleanField = models.BooleanField(null=True, blank=True) + for_internal_metrics = models.BooleanField(default=False) + is_member_join_email_enabled = models.BooleanField(default=True) + enforce_2fa = models.BooleanField(null=True, blank=True) - is_hipaa: models.BooleanField = models.BooleanField(default=False, null=True, blank=True) + is_hipaa = models.BooleanField(default=False, null=True, blank=True) ## Managed by Billing - customer_id: models.CharField = models.CharField(max_length=200, null=True, blank=True) + customer_id = models.CharField(max_length=200, null=True, blank=True) available_product_features = ArrayField(models.JSONField(blank=False), null=True, blank=True) # Managed by Billing, cached here for usage controls # Like { @@ -145,14 +143,14 @@ class PluginsAccessLevel(models.IntegerChoices): # 'period': ['2021-01-01', '2021-01-31'] # } # Also currently indicates if the organization is on billing V2 or not - usage: models.JSONField = models.JSONField(null=True, blank=True) - never_drop_data: models.BooleanField = models.BooleanField(default=False, null=True, blank=True) + usage = models.JSONField(null=True, blank=True) + never_drop_data = models.BooleanField(default=False, null=True, blank=True) # Scoring levels defined in billing::customer::TrustScores - customer_trust_scores: models.JSONField = models.JSONField(default=dict, null=True, blank=True) + customer_trust_scores = models.JSONField(default=dict, null=True, blank=True) # DEPRECATED attributes (should be removed on next major version) - setup_section_2_completed: models.BooleanField = models.BooleanField(default=True) - personalization: models.JSONField = models.JSONField(default=dict, null=False, blank=True) + setup_section_2_completed = models.BooleanField(default=True) + personalization = models.JSONField(default=dict, null=False, blank=True) domain_whitelist: ArrayField = ArrayField( models.CharField(max_length=256, blank=False), blank=True, default=list ) # DEPRECATED in favor of `OrganizationDomain` model; previously used to allow self-serve account creation based on social login (#5111) @@ -260,23 +258,21 @@ class Level(models.IntegerChoices): ADMIN = 8, "administrator" OWNER = 15, "owner" - organization: models.ForeignKey = models.ForeignKey( + organization = models.ForeignKey( "posthog.Organization", on_delete=models.CASCADE, related_name="memberships", related_query_name="membership", ) - user: models.ForeignKey = models.ForeignKey( + user = models.ForeignKey( "posthog.User", on_delete=models.CASCADE, related_name="organization_memberships", related_query_name="organization_membership", ) - level: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField( - default=Level.MEMBER, choices=Level.choices - ) - joined_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) + level = models.PositiveSmallIntegerField(default=Level.MEMBER, choices=Level.choices) + joined_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) class Meta: constraints = [ diff --git a/posthog/models/organization_domain.py b/posthog/models/organization_domain.py index d3b7138d6a56f..0766cd25461b3 100644 --- a/posthog/models/organization_domain.py +++ b/posthog/models/organization_domain.py @@ -117,26 +117,26 @@ def get_sso_enforcement_for_email_address(self, email: str) -> Optional[str]: class OrganizationDomain(UUIDModel): objects: OrganizationDomainManager = OrganizationDomainManager() - organization: models.ForeignKey = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name="domains") - domain: models.CharField = models.CharField(max_length=128, unique=True) - verification_challenge: models.CharField = models.CharField(max_length=128, default=generate_verification_challenge) - verified_at: models.DateTimeField = models.DateTimeField( + organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name="domains") + domain = models.CharField(max_length=128, unique=True) + verification_challenge = models.CharField(max_length=128, default=generate_verification_challenge) + verified_at = models.DateTimeField( null=True, blank=True, default=None ) # verification (through DNS) is only used for PostHog Cloud; on self-hosted we take all domains as verified - last_verification_retry: models.DateTimeField = models.DateTimeField(null=True, blank=True, default=None) - jit_provisioning_enabled: models.BooleanField = models.BooleanField( + last_verification_retry = models.DateTimeField(null=True, blank=True, default=None) + jit_provisioning_enabled = models.BooleanField( default=False ) # Just-in-time automatic provisioning (user accounts are created on the respective org when logging in with any SSO provider) - sso_enforcement: models.CharField = models.CharField( + sso_enforcement = models.CharField( max_length=28, blank=True ) # currently only used for PostHog Cloud; SSO enforcement on self-hosted is set by env var # ---- SAML attributes ---- # Normally not good practice to have `null=True` in `CharField` (as you have to nil states now), but creating non-nullable # attributes locks up tables when migrating. Remove `null=True` on next major release. - saml_entity_id: models.CharField = models.CharField(max_length=512, blank=True, null=True) - saml_acs_url: models.CharField = models.CharField(max_length=512, blank=True, null=True) - saml_x509_cert: models.TextField = models.TextField(blank=True, null=True) + saml_entity_id = models.CharField(max_length=512, blank=True, null=True) + saml_acs_url = models.CharField(max_length=512, blank=True, null=True) + saml_x509_cert = models.TextField(blank=True, null=True) class Meta: verbose_name = "domain" diff --git a/posthog/models/organization_invite.py b/posthog/models/organization_invite.py index be0c30dd6bae9..fc45084626a7d 100644 --- a/posthog/models/organization_invite.py +++ b/posthog/models/organization_invite.py @@ -36,29 +36,29 @@ def validate_private_project_access(value): class OrganizationInvite(UUIDModel): - organization: models.ForeignKey = models.ForeignKey( + organization = models.ForeignKey( "posthog.Organization", on_delete=models.CASCADE, related_name="invites", related_query_name="invite", ) - target_email: models.EmailField = models.EmailField(null=True, db_index=True) - first_name: models.CharField = models.CharField(max_length=30, blank=True, default="") - created_by: models.ForeignKey = models.ForeignKey( + target_email = models.EmailField(null=True, db_index=True) + first_name = models.CharField(max_length=30, blank=True, default="") + created_by = models.ForeignKey( "posthog.User", on_delete=models.SET_NULL, related_name="organization_invites", related_query_name="organization_invite", null=True, ) - emailing_attempt_made: models.BooleanField = models.BooleanField(default=False) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) - message: models.TextField = models.TextField(blank=True, null=True) - level: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField( + emailing_attempt_made = models.BooleanField(default=False) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + message = models.TextField(blank=True, null=True) + level = models.PositiveSmallIntegerField( default=OrganizationMembership.Level.MEMBER, choices=OrganizationMembership.Level.choices ) - private_project_access: models.JSONField = models.JSONField( + private_project_access = models.JSONField( default=list, null=True, blank=True, diff --git a/posthog/models/person/person.py b/posthog/models/person/person.py index b1e4b4b626a99..1c1b62714cc76 100644 --- a/posthog/models/person/person.py +++ b/posthog/models/person/person.py @@ -29,22 +29,22 @@ def distinct_ids_exist(team_id: int, distinct_ids: list[str]) -> bool: class Person(models.Model): _distinct_ids: Optional[list[str]] - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True, blank=True) # used to prevent race conditions with set and set_once - properties_last_updated_at: models.JSONField = models.JSONField(default=dict, null=True, blank=True) + properties_last_updated_at = models.JSONField(default=dict, null=True, blank=True) # used for evaluating if we need to override the value or not (value: set or set_once) - properties_last_operation: models.JSONField = models.JSONField(null=True, blank=True) + properties_last_operation = models.JSONField(null=True, blank=True) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - properties: models.JSONField = models.JSONField(default=dict) - is_user: models.ForeignKey = models.ForeignKey("User", on_delete=models.CASCADE, null=True, blank=True) - is_identified: models.BooleanField = models.BooleanField(default=False) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + properties = models.JSONField(default=dict) + is_user = models.ForeignKey("User", on_delete=models.CASCADE, null=True, blank=True) + is_identified = models.BooleanField(default=False) uuid = models.UUIDField(db_index=True, default=UUIDT, editable=False) # current version of the person, used to sync with ClickHouse and collapse rows correctly - version: models.BigIntegerField = models.BigIntegerField(null=True, blank=True) + version = models.BigIntegerField(null=True, blank=True) # Has an index on properties -> email from migration 0121, (team_id, id DESC) from migration 0164 @@ -121,12 +121,12 @@ class PersonDistinctId(models.Model): class Meta: constraints = [models.UniqueConstraint(fields=["team", "distinct_id"], name="unique distinct_id for team")] - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE, db_index=False) - person: models.ForeignKey = models.ForeignKey(Person, on_delete=models.CASCADE) - distinct_id: models.CharField = models.CharField(max_length=400) + team = models.ForeignKey("Team", on_delete=models.CASCADE, db_index=False) + person = models.ForeignKey(Person, on_delete=models.CASCADE) + distinct_id = models.CharField(max_length=400) # current version of the id, used to sync with ClickHouse and collapse rows correctly for new clickhouse table - version: models.BigIntegerField = models.BigIntegerField(null=True, blank=True) + version = models.BigIntegerField(null=True, blank=True) class PersonlessDistinctId(models.Model): @@ -135,11 +135,11 @@ class Meta: models.UniqueConstraint(fields=["team", "distinct_id"], name="unique personless distinct_id for team") ] - id: models.BigAutoField = models.BigAutoField(primary_key=True) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE, db_index=False) - distinct_id: models.CharField = models.CharField(max_length=400) - is_merged: models.BooleanField = models.BooleanField(default=False) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) + id = models.BigAutoField(primary_key=True) + team = models.ForeignKey("Team", on_delete=models.CASCADE, db_index=False) + distinct_id = models.CharField(max_length=400) + is_merged = models.BooleanField(default=False) + created_at = models.DateTimeField(auto_now_add=True, blank=True) class PersonOverrideMapping(models.Model): @@ -169,23 +169,23 @@ class PersonOverride(models.Model): """ id = models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID") - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) + team = models.ForeignKey("Team", on_delete=models.CASCADE) - old_person_id: models.ForeignKey = models.ForeignKey( + old_person_id = models.ForeignKey( "PersonOverrideMapping", db_column="old_person_id", related_name="person_override_old", on_delete=models.CASCADE, ) - override_person_id: models.ForeignKey = models.ForeignKey( + override_person_id = models.ForeignKey( "PersonOverrideMapping", db_column="override_person_id", related_name="person_override_override", on_delete=models.CASCADE, ) - oldest_event: models.DateTimeField = models.DateTimeField() - version: models.BigIntegerField = models.BigIntegerField(null=True, blank=True) + oldest_event = models.DateTimeField() + version = models.BigIntegerField(null=True, blank=True) class Meta: constraints = [ diff --git a/posthog/models/personal_api_key.py b/posthog/models/personal_api_key.py index fe23d8f66fdff..ea886b55757c6 100644 --- a/posthog/models/personal_api_key.py +++ b/posthog/models/personal_api_key.py @@ -41,19 +41,19 @@ def mask_key_value(value: str) -> str: class PersonalAPIKey(models.Model): - id: models.CharField = models.CharField(primary_key=True, max_length=50, default=generate_random_token) + id = models.CharField(primary_key=True, max_length=50, default=generate_random_token) user = models.ForeignKey("posthog.User", on_delete=models.CASCADE, related_name="personal_api_keys") - label: models.CharField = models.CharField(max_length=40) - value: models.CharField = models.CharField(unique=True, max_length=50, editable=False, null=True, blank=True) - mask_value: models.CharField = models.CharField(max_length=11, editable=False, null=True) - secure_value: models.CharField = models.CharField( + label = models.CharField(max_length=40) + value = models.CharField(unique=True, max_length=50, editable=False, null=True, blank=True) + mask_value = models.CharField(max_length=11, editable=False, null=True) + secure_value = models.CharField( unique=True, max_length=300, null=True, editable=False, ) - created_at: models.DateTimeField = models.DateTimeField(default=timezone.now) - last_used_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) + created_at = models.DateTimeField(default=timezone.now) + last_used_at = models.DateTimeField(null=True, blank=True) scopes: ArrayField = ArrayField(models.CharField(max_length=100), null=True) scoped_teams: ArrayField = ArrayField(models.IntegerField(), null=True) scoped_organizations: ArrayField = ArrayField(models.CharField(max_length=100), null=True) diff --git a/posthog/models/plugin.py b/posthog/models/plugin.py index 19d07578cf4a5..08d8e28ed696a 100644 --- a/posthog/models/plugin.py +++ b/posthog/models/plugin.py @@ -151,49 +151,47 @@ class PluginType(models.TextChoices): ) # Code checked into plugin_server, url starts with "inline:" # DEPRECATED: plugin-server will own all plugin code, org relations don't make sense - organization: models.ForeignKey = models.ForeignKey( + organization = models.ForeignKey( "posthog.Organization", on_delete=models.CASCADE, related_name="plugins", related_query_name="plugin", null=True, ) - plugin_type: models.CharField = models.CharField( - max_length=200, null=True, blank=True, choices=PluginType.choices, default=None - ) - is_global: models.BooleanField = models.BooleanField(default=False) # Whether plugin is installed for all orgs - is_preinstalled: models.BooleanField = models.BooleanField(default=False) - is_stateless: models.BooleanField = models.BooleanField( + plugin_type = models.CharField(max_length=200, null=True, blank=True, choices=PluginType.choices, default=None) + is_global = models.BooleanField(default=False) # Whether plugin is installed for all orgs + is_preinstalled = models.BooleanField(default=False) + is_stateless = models.BooleanField( default=False, null=True, blank=True ) # Whether plugin can run one VM across teams - name: models.CharField = models.CharField(max_length=200, null=True, blank=True) - description: models.TextField = models.TextField(null=True, blank=True) - url: models.CharField = models.CharField(max_length=800, null=True, blank=True, unique=True) - icon: models.CharField = models.CharField(max_length=800, null=True, blank=True) + name = models.CharField(max_length=200, null=True, blank=True) + description = models.TextField(null=True, blank=True) + url = models.CharField(max_length=800, null=True, blank=True, unique=True) + icon = models.CharField(max_length=800, null=True, blank=True) # Describe the fields to ask in the interface; store answers in PluginConfig->config # - config_schema = { [fieldKey]: { name: 'api key', type: 'string', default: '', required: true } } - config_schema: models.JSONField = models.JSONField(default=dict, blank=True) - tag: models.CharField = models.CharField(max_length=200, null=True, blank=True) - archive: models.BinaryField = models.BinaryField(blank=True, null=True) - latest_tag: models.CharField = models.CharField(max_length=800, null=True, blank=True) - latest_tag_checked_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) - capabilities: models.JSONField = models.JSONField(default=dict) - metrics: models.JSONField = models.JSONField(default=dict, null=True, blank=True) - public_jobs: models.JSONField = models.JSONField(default=dict, null=True, blank=True) + config_schema = models.JSONField(default=dict, blank=True) + tag = models.CharField(max_length=200, null=True, blank=True) + archive = models.BinaryField(blank=True, null=True) + latest_tag = models.CharField(max_length=800, null=True, blank=True) + latest_tag_checked_at = models.DateTimeField(null=True, blank=True) + capabilities = models.JSONField(default=dict) + metrics = models.JSONField(default=dict, null=True, blank=True) + public_jobs = models.JSONField(default=dict, null=True, blank=True) # DEPRECATED: not used for anything, all install and config errors are in PluginConfig.error - error: models.JSONField = models.JSONField(default=None, null=True, blank=True) + error = models.JSONField(default=None, null=True, blank=True) # DEPRECATED: this was used when syncing posthog.json with the db on app start - from_json: models.BooleanField = models.BooleanField(default=False) + from_json = models.BooleanField(default=False) # DEPRECATED: this was used when syncing posthog.json with the db on app start - from_web: models.BooleanField = models.BooleanField(default=False) + from_web = models.BooleanField(default=False) # DEPRECATED: using PluginSourceFile model instead - source: models.TextField = models.TextField(blank=True, null=True) + source = models.TextField(blank=True, null=True) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - updated_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) - log_level: models.IntegerField = models.IntegerField(null=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(null=True, blank=True) + log_level = models.IntegerField(null=True, blank=True) # Some plugins are private, only certain organizations should be able to access them # Sometimes we want to deprecate plugins, where the first step is limiting access to organizations using them @@ -226,29 +224,29 @@ def get_default_config(self) -> dict[str, Any]: class PluginConfig(models.Model): - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE, null=True) - plugin: models.ForeignKey = models.ForeignKey("Plugin", on_delete=models.CASCADE) - enabled: models.BooleanField = models.BooleanField(default=False) - order: models.IntegerField = models.IntegerField() - config: models.JSONField = models.JSONField(default=dict) + team = models.ForeignKey("Team", on_delete=models.CASCADE, null=True) + plugin = models.ForeignKey("Plugin", on_delete=models.CASCADE) + enabled = models.BooleanField(default=False) + order = models.IntegerField() + config = models.JSONField(default=dict) # DEPRECATED: use `plugin_log_entries` or `app_metrics` in ClickHouse instead # Error when running this plugin on an event (frontend: PluginErrorType) # - e.g: "undefined is not a function on index.js line 23" # - error = { message: "Exception in processEvent()", time: "iso-string", ...meta } - error: models.JSONField = models.JSONField(default=None, null=True, blank=True) + error = models.JSONField(default=None, null=True, blank=True) # Used to access site.ts from a public URL - web_token: models.CharField = models.CharField(max_length=64, default=None, null=True) + web_token = models.CharField(max_length=64, default=None, null=True) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) # Used in the frontend - name: models.CharField = models.CharField(max_length=400, null=True, blank=True) - description: models.CharField = models.CharField(max_length=1000, null=True, blank=True) + name = models.CharField(max_length=400, null=True, blank=True) + description = models.CharField(max_length=1000, null=True, blank=True) # Used in the frontend to hide pluginConfigs that user deleted - deleted: models.BooleanField = models.BooleanField(default=False, null=True) + deleted = models.BooleanField(default=False, null=True) # If set we will filter the plugin triggers for this event - filters: models.JSONField = models.JSONField(null=True, blank=True) + filters = models.JSONField(null=True, blank=True) # DEPRECATED - this never actually got used - filters is the way to go match_action = models.ForeignKey( @@ -267,13 +265,13 @@ class Meta: class PluginAttachment(models.Model): - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE, null=True) - plugin_config: models.ForeignKey = models.ForeignKey("PluginConfig", on_delete=models.CASCADE, null=True) - key: models.CharField = models.CharField(max_length=200) - content_type: models.CharField = models.CharField(max_length=200) - file_name: models.CharField = models.CharField(max_length=200) - file_size: models.IntegerField = models.IntegerField() - contents: models.BinaryField = models.BinaryField() + team = models.ForeignKey("Team", on_delete=models.CASCADE, null=True) + plugin_config = models.ForeignKey("PluginConfig", on_delete=models.CASCADE, null=True) + key = models.CharField(max_length=200) + content_type = models.CharField(max_length=200) + file_name = models.CharField(max_length=200) + file_size = models.IntegerField() + contents = models.BinaryField() class PluginStorage(models.Model): @@ -285,9 +283,9 @@ class Meta: ) ] - plugin_config: models.ForeignKey = models.ForeignKey("PluginConfig", on_delete=models.CASCADE) - key: models.CharField = models.CharField(max_length=200) - value: models.TextField = models.TextField(blank=True, null=True) + plugin_config = models.ForeignKey("PluginConfig", on_delete=models.CASCADE) + key = models.CharField(max_length=200) + value = models.TextField(blank=True, null=True) class PluginLogEntrySource(StrEnum): @@ -401,14 +399,14 @@ class Status(models.TextChoices): TRANSPILED = "TRANSPILED", "transpiled" ERROR = "ERROR", "error" - plugin: models.ForeignKey = models.ForeignKey("Plugin", on_delete=models.CASCADE) - filename: models.CharField = models.CharField(max_length=200, blank=False) + plugin = models.ForeignKey("Plugin", on_delete=models.CASCADE) + filename = models.CharField(max_length=200, blank=False) # "source" can be null if we're only using this model to cache transpiled code from a ".zip" - source: models.TextField = models.TextField(blank=True, null=True) - status: models.CharField = models.CharField(max_length=20, choices=Status.choices, null=True) - transpiled: models.TextField = models.TextField(blank=True, null=True) - error: models.TextField = models.TextField(blank=True, null=True) - updated_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) + source = models.TextField(blank=True, null=True) + status = models.CharField(max_length=20, choices=Status.choices, null=True) + transpiled = models.TextField(blank=True, null=True) + error = models.TextField(blank=True, null=True) + updated_at = models.DateTimeField(null=True, blank=True) objects: PluginSourceFileManager = PluginSourceFileManager() diff --git a/posthog/models/project.py b/posthog/models/project.py index 900c6fbed32cf..5bf82245db590 100644 --- a/posthog/models/project.py +++ b/posthog/models/project.py @@ -28,19 +28,19 @@ class Project(models.Model): `Project` is part of the environemnts feature, which is a work in progress. """ - id: models.BigIntegerField = models.BigIntegerField(primary_key=True, verbose_name="ID") - organization: models.ForeignKey = models.ForeignKey( + id = models.BigIntegerField(primary_key=True, verbose_name="ID") + organization = models.ForeignKey( "posthog.Organization", on_delete=models.CASCADE, related_name="projects", related_query_name="project", ) - name: models.CharField = models.CharField( + name = models.CharField( max_length=200, default="Default project", validators=[MinLengthValidator(1, "Project must have a name!")], ) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) + created_at = models.DateTimeField(auto_now_add=True) objects: ProjectManager = ProjectManager() diff --git a/posthog/models/property_definition.py b/posthog/models/property_definition.py index 99196d1ff78e6..e2e77eba2148c 100644 --- a/posthog/models/property_definition.py +++ b/posthog/models/property_definition.py @@ -37,23 +37,23 @@ class Type(models.IntegerChoices): GROUP = 3, "group" SESSION = 4, "session" - team: models.ForeignKey = models.ForeignKey( + team = models.ForeignKey( Team, on_delete=models.CASCADE, related_name="property_definitions", related_query_name="team", ) - name: models.CharField = models.CharField(max_length=400) - is_numerical: models.BooleanField = models.BooleanField( + name = models.CharField(max_length=400) + is_numerical = models.BooleanField( default=False ) # whether the property can be interpreted as a number, and therefore used for math aggregation operations property_type = models.CharField(max_length=50, choices=PropertyType.choices, blank=True, null=True) # :TRICKY: May be null for historical events - type: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField(default=Type.EVENT, choices=Type.choices) + type = models.PositiveSmallIntegerField(default=Type.EVENT, choices=Type.choices) # Only populated for `Type.GROUP` - group_type_index: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField(null=True) + group_type_index = models.PositiveSmallIntegerField(null=True) # DEPRECATED property_type_format = models.CharField( @@ -61,11 +61,11 @@ class Type(models.IntegerChoices): ) # Deprecated in #8292 # DEPRECATED - volume_30_day: models.IntegerField = models.IntegerField(default=None, null=True) # Deprecated in #4480 + volume_30_day = models.IntegerField(default=None, null=True) # Deprecated in #4480 # DEPRECATED # Number of times an insight has been saved with this property in its filter in the last 30 rolling days (computed asynchronously when stars align) - query_usage_30_day: models.IntegerField = models.IntegerField(default=None, null=True) + query_usage_30_day = models.IntegerField(default=None, null=True) class Meta: indexes = [ diff --git a/posthog/models/proxy_record.py b/posthog/models/proxy_record.py index 3c421f4a0bb7c..c69f9d96d196e 100644 --- a/posthog/models/proxy_record.py +++ b/posthog/models/proxy_record.py @@ -4,12 +4,10 @@ class ProxyRecord(UUIDModel): - organization: models.ForeignKey = models.ForeignKey( - Organization, on_delete=models.CASCADE, related_name="proxy_records" - ) - domain: models.CharField = models.CharField(max_length=64, unique=True) - target_cname: models.CharField = models.CharField(max_length=256, null=False) - message: models.CharField = models.CharField(max_length=1024, null=True) + organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name="proxy_records") + domain = models.CharField(max_length=64, unique=True) + target_cname = models.CharField(max_length=256, null=False) + message = models.CharField(max_length=1024, null=True) class Status(models.TextChoices): WAITING = "waiting" @@ -19,15 +17,15 @@ class Status(models.TextChoices): DELETING = "deleting" TIMED_OUT = "timed_out" - status: models.CharField = models.CharField( + status = models.CharField( choices=Status.choices, default=Status.WAITING, ) - created_by: models.ForeignKey = models.ForeignKey( + created_by = models.ForeignKey( "posthog.User", on_delete=models.SET_NULL, null=True, ) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) diff --git a/posthog/models/scheduled_change.py b/posthog/models/scheduled_change.py index ee92cc59c506e..9b1d96c08cacf 100644 --- a/posthog/models/scheduled_change.py +++ b/posthog/models/scheduled_change.py @@ -6,17 +6,17 @@ class AllowedModels(models.TextChoices): FEATURE_FLAG = "FeatureFlag", "feature flag" id = models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID") - record_id: models.CharField = models.CharField(max_length=200) - model_name: models.CharField = models.CharField(max_length=100, choices=AllowedModels.choices) - payload: models.JSONField = models.JSONField(default=dict) - scheduled_at: models.DateTimeField = models.DateTimeField() - executed_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) + record_id = models.CharField(max_length=200) + model_name = models.CharField(max_length=100, choices=AllowedModels.choices) + payload = models.JSONField(default=dict) + scheduled_at = models.DateTimeField() + executed_at = models.DateTimeField(null=True, blank=True) failure_reason = models.CharField(max_length=400, null=True, blank=True) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + created_at = models.DateTimeField(auto_now_add=True) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True) + updated_at = models.DateTimeField(auto_now_add=True) class Meta: indexes = [ diff --git a/posthog/models/sharing_configuration.py b/posthog/models/sharing_configuration.py index 7bbacc453559d..84cbb400ce700 100644 --- a/posthog/models/sharing_configuration.py +++ b/posthog/models/sharing_configuration.py @@ -12,10 +12,10 @@ def get_default_access_token() -> str: class SharingConfiguration(models.Model): # Relations - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) + team = models.ForeignKey("Team", on_delete=models.CASCADE) dashboard = models.ForeignKey("posthog.Dashboard", on_delete=models.CASCADE, null=True) insight = models.ForeignKey("posthog.Insight", on_delete=models.CASCADE, null=True) - recording: models.ForeignKey = models.ForeignKey( + recording = models.ForeignKey( "SessionRecording", related_name="sharing_configurations", on_delete=models.CASCADE, @@ -24,10 +24,10 @@ class SharingConfiguration(models.Model): blank=True, ) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True, blank=True) - enabled: models.BooleanField = models.BooleanField(default=False) - access_token: models.CharField = models.CharField( + enabled = models.BooleanField(default=False) + access_token = models.CharField( max_length=400, null=True, blank=True, diff --git a/posthog/models/subscription.py b/posthog/models/subscription.py index 6bd742015f252..ef0d25bd9d070 100644 --- a/posthog/models/subscription.py +++ b/posthog/models/subscription.py @@ -74,36 +74,36 @@ class SubscriptionByWeekDay(models.TextChoices): SUNDAY = "sunday" # Relations - i.e. WHAT are we exporting? - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) + team = models.ForeignKey("Team", on_delete=models.CASCADE) dashboard = models.ForeignKey("posthog.Dashboard", on_delete=models.CASCADE, null=True) insight = models.ForeignKey("posthog.Insight", on_delete=models.CASCADE, null=True) # Subscription type (email, slack etc.) - title: models.CharField = models.CharField(max_length=100, null=True, blank=True) - target_type: models.CharField = models.CharField(max_length=10, choices=SubscriptionTarget.choices) - target_value: models.TextField = models.TextField() + title = models.CharField(max_length=100, null=True, blank=True) + target_type = models.CharField(max_length=10, choices=SubscriptionTarget.choices) + target_value = models.TextField() # Subscription delivery (related to rrule) - frequency: models.CharField = models.CharField(max_length=10, choices=SubscriptionFrequency.choices) - interval: models.IntegerField = models.IntegerField(default=1) - count: models.IntegerField = models.IntegerField(null=True) + frequency = models.CharField(max_length=10, choices=SubscriptionFrequency.choices) + interval = models.IntegerField(default=1) + count = models.IntegerField(null=True) byweekday: ArrayField = ArrayField( models.CharField(max_length=10, choices=SubscriptionByWeekDay.choices), null=True, blank=True, default=None, ) - bysetpos: models.IntegerField = models.IntegerField(null=True) - start_date: models.DateTimeField = models.DateTimeField() - until_date: models.DateTimeField = models.DateTimeField(null=True, blank=True) + bysetpos = models.IntegerField(null=True) + start_date = models.DateTimeField() + until_date = models.DateTimeField(null=True, blank=True) # Controlled field - next schedule as helper for - next_delivery_date: models.DateTimeField = models.DateTimeField(null=True, blank=True) + next_delivery_date = models.DateTimeField(null=True, blank=True) # Meta - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) - deleted: models.BooleanField = models.BooleanField(default=False) + created_at = models.DateTimeField(auto_now_add=True, blank=True) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) + deleted = models.BooleanField(default=False) def save(self, *args, **kwargs) -> None: # Only if the schedule has changed do we update the next delivery date diff --git a/posthog/models/tag.py b/posthog/models/tag.py index fbe3e262e3c3e..55455c49fb542 100644 --- a/posthog/models/tag.py +++ b/posthog/models/tag.py @@ -8,8 +8,8 @@ def tagify(tag: str): class Tag(UUIDModel): - name: models.CharField = models.CharField(max_length=255) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) + name = models.CharField(max_length=255) + team = models.ForeignKey("Team", on_delete=models.CASCADE) class Meta: unique_together = ("name", "team") diff --git a/posthog/models/tagged_item.py b/posthog/models/tagged_item.py index 302adcdb24f23..7fcc1f7bc262a 100644 --- a/posthog/models/tagged_item.py +++ b/posthog/models/tagged_item.py @@ -55,46 +55,46 @@ class TaggedItem(UUIDModel): https://docs.djangoproject.com/en/4.0/ref/contrib/contenttypes/#generic-relations """ - tag: models.ForeignKey = models.ForeignKey("Tag", on_delete=models.CASCADE, related_name="tagged_items") + tag = models.ForeignKey("Tag", on_delete=models.CASCADE, related_name="tagged_items") # When adding a new taggeditem-model relationship, make sure to add the foreign key field and append field name to # the `RELATED_OBJECTS` tuple above. - dashboard: models.ForeignKey = models.ForeignKey( + dashboard = models.ForeignKey( "Dashboard", on_delete=models.CASCADE, null=True, blank=True, related_name="tagged_items", ) - insight: models.ForeignKey = models.ForeignKey( + insight = models.ForeignKey( "Insight", on_delete=models.CASCADE, null=True, blank=True, related_name="tagged_items", ) - event_definition: models.ForeignKey = models.ForeignKey( + event_definition = models.ForeignKey( "EventDefinition", on_delete=models.CASCADE, null=True, blank=True, related_name="tagged_items", ) - property_definition: models.ForeignKey = models.ForeignKey( + property_definition = models.ForeignKey( "PropertyDefinition", on_delete=models.CASCADE, null=True, blank=True, related_name="tagged_items", ) - action: models.ForeignKey = models.ForeignKey( + action = models.ForeignKey( "Action", on_delete=models.CASCADE, null=True, blank=True, related_name="tagged_items", ) - feature_flag: models.ForeignKey = models.ForeignKey( + feature_flag = models.ForeignKey( "FeatureFlag", on_delete=models.CASCADE, null=True, diff --git a/posthog/models/team/team.py b/posthog/models/team/team.py index 57928b39444a1..bcb0b236c75d4 100644 --- a/posthog/models/team/team.py +++ b/posthog/models/team/team.py @@ -178,44 +178,44 @@ class Meta: ) ] - organization: models.ForeignKey = models.ForeignKey( + organization = models.ForeignKey( "posthog.Organization", on_delete=models.CASCADE, related_name="teams", related_query_name="team", ) - project: models.ForeignKey = models.ForeignKey( + project = models.ForeignKey( "posthog.Project", on_delete=models.CASCADE, related_name="teams", related_query_name="team", null=True, ) - api_token: models.CharField = models.CharField( + api_token = models.CharField( max_length=200, unique=True, default=generate_random_token_project, validators=[MinLengthValidator(10, "Project's API token must be at least 10 characters long!")], ) app_urls: ArrayField = ArrayField(models.CharField(max_length=200, null=True), default=list, blank=True) - name: models.CharField = models.CharField( + name = models.CharField( max_length=200, default="Default project", validators=[MinLengthValidator(1, "Project must have a name!")], ) - slack_incoming_webhook: models.CharField = models.CharField(max_length=500, null=True, blank=True) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True) - anonymize_ips: models.BooleanField = models.BooleanField(default=False) - completed_snippet_onboarding: models.BooleanField = models.BooleanField(default=False) - has_completed_onboarding_for: models.JSONField = models.JSONField(null=True, blank=True) - ingested_event: models.BooleanField = models.BooleanField(default=False) - autocapture_opt_out: models.BooleanField = models.BooleanField(null=True, blank=True) - autocapture_web_vitals_opt_in: models.BooleanField = models.BooleanField(null=True, blank=True) - autocapture_exceptions_opt_in: models.BooleanField = models.BooleanField(null=True, blank=True) - autocapture_exceptions_errors_to_ignore: models.JSONField = models.JSONField(null=True, blank=True) - session_recording_opt_in: models.BooleanField = models.BooleanField(default=False) - session_recording_sample_rate: models.DecimalField = models.DecimalField( + slack_incoming_webhook = models.CharField(max_length=500, null=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + anonymize_ips = models.BooleanField(default=False) + completed_snippet_onboarding = models.BooleanField(default=False) + has_completed_onboarding_for = models.JSONField(null=True, blank=True) + ingested_event = models.BooleanField(default=False) + autocapture_opt_out = models.BooleanField(null=True, blank=True) + autocapture_web_vitals_opt_in = models.BooleanField(null=True, blank=True) + autocapture_exceptions_opt_in = models.BooleanField(null=True, blank=True) + autocapture_exceptions_errors_to_ignore = models.JSONField(null=True, blank=True) + session_recording_opt_in = models.BooleanField(default=False) + session_recording_sample_rate = models.DecimalField( # will store a decimal between 0 and 1 allowing up to 2 decimal places null=True, blank=True, @@ -223,39 +223,37 @@ class Meta: decimal_places=2, validators=[MinValueValidator(Decimal(0)), MaxValueValidator(Decimal(1))], ) - session_recording_minimum_duration_milliseconds: models.IntegerField = models.IntegerField( + session_recording_minimum_duration_milliseconds = models.IntegerField( null=True, blank=True, validators=[MinValueValidator(0), MaxValueValidator(15000)], ) - session_recording_linked_flag: models.JSONField = models.JSONField(null=True, blank=True) - session_recording_network_payload_capture_config: models.JSONField = models.JSONField(null=True, blank=True) - session_replay_config: models.JSONField = models.JSONField(null=True, blank=True) - capture_console_log_opt_in: models.BooleanField = models.BooleanField(null=True, blank=True) - capture_performance_opt_in: models.BooleanField = models.BooleanField(null=True, blank=True) - surveys_opt_in: models.BooleanField = models.BooleanField(null=True, blank=True) - heatmaps_opt_in: models.BooleanField = models.BooleanField(null=True, blank=True) - session_recording_version: models.CharField = models.CharField(null=True, blank=True, max_length=24) - signup_token: models.CharField = models.CharField(max_length=200, null=True, blank=True) - is_demo: models.BooleanField = models.BooleanField(default=False) - access_control: models.BooleanField = models.BooleanField(default=False) - week_start_day: models.SmallIntegerField = models.SmallIntegerField( - null=True, blank=True, choices=WeekStartDay.choices - ) + session_recording_linked_flag = models.JSONField(null=True, blank=True) + session_recording_network_payload_capture_config = models.JSONField(null=True, blank=True) + session_replay_config = models.JSONField(null=True, blank=True) + capture_console_log_opt_in = models.BooleanField(null=True, blank=True) + capture_performance_opt_in = models.BooleanField(null=True, blank=True) + surveys_opt_in = models.BooleanField(null=True, blank=True) + heatmaps_opt_in = models.BooleanField(null=True, blank=True) + session_recording_version = models.CharField(null=True, blank=True, max_length=24) + signup_token = models.CharField(max_length=200, null=True, blank=True) + is_demo = models.BooleanField(default=False) + access_control = models.BooleanField(default=False) + week_start_day = models.SmallIntegerField(null=True, blank=True, choices=WeekStartDay.choices) # This is not a manual setting. It's updated automatically to reflect if the team uses site apps or not. - inject_web_apps: models.BooleanField = models.BooleanField(null=True) + inject_web_apps = models.BooleanField(null=True) - test_account_filters: models.JSONField = models.JSONField(default=list) - test_account_filters_default_checked: models.BooleanField = models.BooleanField(null=True, blank=True) + test_account_filters = models.JSONField(default=list) + test_account_filters_default_checked = models.BooleanField(null=True, blank=True) - path_cleaning_filters: models.JSONField = models.JSONField(default=list, null=True, blank=True) - timezone: models.CharField = models.CharField(max_length=240, choices=TIMEZONES, default="UTC") - data_attributes: models.JSONField = models.JSONField(default=get_default_data_attributes) + path_cleaning_filters = models.JSONField(default=list, null=True, blank=True) + timezone = models.CharField(max_length=240, choices=TIMEZONES, default="UTC") + data_attributes = models.JSONField(default=get_default_data_attributes) person_display_name_properties: ArrayField = ArrayField(models.CharField(max_length=400), null=True, blank=True) live_events_columns: ArrayField = ArrayField(models.TextField(), null=True, blank=True) recording_domains: ArrayField = ArrayField(models.CharField(max_length=200, null=True), blank=True, null=True) - primary_dashboard: models.ForeignKey = models.ForeignKey( + primary_dashboard = models.ForeignKey( "posthog.Dashboard", on_delete=models.SET_NULL, null=True, @@ -266,10 +264,10 @@ class Meta: # Generic field for storing any team-specific context that is more temporary in nature and thus # likely doesn't deserve a dedicated column. Can be used for things like settings and overrides # during feature releases. - extra_settings: models.JSONField = models.JSONField(null=True, blank=True) + extra_settings = models.JSONField(null=True, blank=True) # Project level default HogQL query modifiers - modifiers: models.JSONField = models.JSONField(null=True, blank=True) + modifiers = models.JSONField(null=True, blank=True) # This is meant to be used as a stopgap until https://github.com/PostHog/meta/pull/39 gets implemented # Switches _most_ queries to using distinct_id as aggregator instead of person_id @@ -285,22 +283,20 @@ def aggregate_users_by_distinct_id(self) -> bool: correlation_config = models.JSONField(default=dict, null=True, blank=True) # DEPRECATED, DISUSED: recordings on CH are cleared with Clickhouse's TTL - session_recording_retention_period_days: models.IntegerField = models.IntegerField( - null=True, default=None, blank=True - ) + session_recording_retention_period_days = models.IntegerField(null=True, default=None, blank=True) # DEPRECATED, DISUSED: plugins are enabled for everyone now - plugins_opt_in: models.BooleanField = models.BooleanField(default=False) + plugins_opt_in = models.BooleanField(default=False) # DEPRECATED, DISUSED: replaced with env variable OPT_OUT_CAPTURE and User.anonymized_data - opt_out_capture: models.BooleanField = models.BooleanField(default=False) + opt_out_capture = models.BooleanField(default=False) # DEPRECATED: in favor of `EventDefinition` model - event_names: models.JSONField = models.JSONField(default=list, blank=True) - event_names_with_usage: models.JSONField = models.JSONField(default=list, blank=True) + event_names = models.JSONField(default=list, blank=True) + event_names_with_usage = models.JSONField(default=list, blank=True) # DEPRECATED: in favor of `PropertyDefinition` model - event_properties: models.JSONField = models.JSONField(default=list, blank=True) - event_properties_with_usage: models.JSONField = models.JSONField(default=list, blank=True) - event_properties_numerical: models.JSONField = models.JSONField(default=list, blank=True) - external_data_workspace_id: models.CharField = models.CharField(max_length=400, null=True, blank=True) - external_data_workspace_last_synced_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) + event_properties = models.JSONField(default=list, blank=True) + event_properties_with_usage = models.JSONField(default=list, blank=True) + event_properties_numerical = models.JSONField(default=list, blank=True) + external_data_workspace_id = models.CharField(max_length=400, null=True, blank=True) + external_data_workspace_last_synced_at = models.DateTimeField(null=True, blank=True) objects: TeamManager = TeamManager() diff --git a/posthog/models/uploaded_media.py b/posthog/models/uploaded_media.py index 2b31f348263cb..8810d13616ddc 100644 --- a/posthog/models/uploaded_media.py +++ b/posthog/models/uploaded_media.py @@ -20,15 +20,15 @@ class ObjectStorageUnavailable(Exception): class UploadedMedia(UUIDModel): - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + created_at = models.DateTimeField(auto_now_add=True, blank=True) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) # path in object storage or some other location identifier for the asset # 1000 characters would hold a 20 UUID forward slash separated path with space to spare - media_location: models.TextField = models.TextField(null=True, blank=True, max_length=1000) - content_type: models.TextField = models.TextField(null=True, blank=True, max_length=100) - file_name: models.TextField = models.TextField(null=True, blank=True, max_length=1000) + media_location = models.TextField(null=True, blank=True, max_length=1000) + content_type = models.TextField(null=True, blank=True, max_length=100) + file_name = models.TextField(null=True, blank=True, max_length=1000) def get_absolute_url(self) -> str: return absolute_uri(f"/uploaded_media/{self.id}") diff --git a/posthog/models/user.py b/posthog/models/user.py index f896ab7bb9a6b..621c1d36429a7 100644 --- a/posthog/models/user.py +++ b/posthog/models/user.py @@ -140,28 +140,26 @@ class User(AbstractUser, UUIDClassicModel): current_team = models.ForeignKey("posthog.Team", models.SET_NULL, null=True, related_name="teams_currently+") email = models.EmailField(_("email address"), unique=True) pending_email = models.EmailField(_("pending email address awaiting verification"), null=True, blank=True) - temporary_token: models.CharField = models.CharField(max_length=200, null=True, blank=True, unique=True) - distinct_id: models.CharField = models.CharField(max_length=200, null=True, blank=True, unique=True) - is_email_verified: models.BooleanField = models.BooleanField(null=True, blank=True) - requested_password_reset_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) - has_seen_product_intro_for: models.JSONField = models.JSONField(null=True, blank=True) - strapi_id: models.PositiveSmallIntegerField = models.PositiveSmallIntegerField(null=True, blank=True) + temporary_token = models.CharField(max_length=200, null=True, blank=True, unique=True) + distinct_id = models.CharField(max_length=200, null=True, blank=True, unique=True) + is_email_verified = models.BooleanField(null=True, blank=True) + requested_password_reset_at = models.DateTimeField(null=True, blank=True) + has_seen_product_intro_for = models.JSONField(null=True, blank=True) + strapi_id = models.PositiveSmallIntegerField(null=True, blank=True) # Preferences / configuration options - theme_mode: models.CharField = models.CharField(max_length=20, null=True, blank=True, choices=ThemeMode.choices) + theme_mode = models.CharField(max_length=20, null=True, blank=True, choices=ThemeMode.choices) # These override the notification settings - partial_notification_settings: models.JSONField = models.JSONField(null=True, blank=True) - anonymize_data: models.BooleanField = models.BooleanField(default=False, null=True, blank=True) - toolbar_mode: models.CharField = models.CharField( - max_length=200, null=True, blank=True, choices=TOOLBAR_CHOICES, default=TOOLBAR - ) - hedgehog_config: models.JSONField = models.JSONField(null=True, blank=True) + partial_notification_settings = models.JSONField(null=True, blank=True) + anonymize_data = models.BooleanField(default=False, null=True, blank=True) + toolbar_mode = models.CharField(max_length=200, null=True, blank=True, choices=TOOLBAR_CHOICES, default=TOOLBAR) + hedgehog_config = models.JSONField(null=True, blank=True) # DEPRECATED - events_column_config: models.JSONField = models.JSONField(default=events_column_config_default) + events_column_config = models.JSONField(default=events_column_config_default) # DEPRECATED - Most emails are done via 3rd parties and we use their opt/in out tooling - email_opt_in: models.BooleanField = models.BooleanField(default=False, null=True, blank=True) + email_opt_in = models.BooleanField(default=False, null=True, blank=True) # Remove unused attributes from `AbstractUser` username = None diff --git a/posthog/models/user_scene_personalisation.py b/posthog/models/user_scene_personalisation.py index 8b745f67a6808..fe19406ebe121 100644 --- a/posthog/models/user_scene_personalisation.py +++ b/posthog/models/user_scene_personalisation.py @@ -4,10 +4,10 @@ class UserScenePersonalisation(UUIDModel): - scene: models.CharField = models.CharField(max_length=200) - dashboard: models.ForeignKey = models.ForeignKey("Dashboard", on_delete=models.CASCADE, null=True, blank=True) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE, null=True, blank=True) - user: models.ForeignKey = models.ForeignKey( + scene = models.CharField(max_length=200) + dashboard = models.ForeignKey("Dashboard", on_delete=models.CASCADE, null=True, blank=True) + team = models.ForeignKey("Team", on_delete=models.CASCADE, null=True, blank=True) + user = models.ForeignKey( "User", on_delete=models.CASCADE, null=True, diff --git a/posthog/models/utils.py b/posthog/models/utils.py index 796c47ee3d163..22b84bc5f1761 100644 --- a/posthog/models/utils.py +++ b/posthog/models/utils.py @@ -139,23 +139,23 @@ def uuid7(unix_ms_time: Optional[Union[int, str]] = None, random: Optional[Union class CreatedMetaFields(models.Model): - created_by: models.ForeignKey = models.ForeignKey("posthog.User", on_delete=models.SET_NULL, null=True, blank=True) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True) + created_by = models.ForeignKey("posthog.User", on_delete=models.SET_NULL, null=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True) class Meta: abstract = True class UpdatedMetaFields(models.Model): - updated_at: models.DateTimeField = models.DateTimeField(auto_now=True, null=True, blank=True) + updated_at = models.DateTimeField(auto_now=True, null=True, blank=True) class Meta: abstract = True class DeletedMetaFields(models.Model): - deleted: models.BooleanField = models.BooleanField(null=True, blank=True, default=False) - deleted_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) + deleted = models.BooleanField(null=True, blank=True, default=False) + deleted_at = models.DateTimeField(null=True, blank=True) class Meta: abstract = True @@ -167,7 +167,7 @@ class UUIDModel(models.Model): class Meta: abstract = True - id: models.UUIDField = models.UUIDField(primary_key=True, default=UUIDT, editable=False) + id = models.UUIDField(primary_key=True, default=UUIDT, editable=False) class UUIDClassicModel(models.Model): @@ -176,7 +176,7 @@ class UUIDClassicModel(models.Model): class Meta: abstract = True - uuid: models.UUIDField = models.UUIDField(unique=True, default=UUIDT, editable=False) + uuid = models.UUIDField(unique=True, default=UUIDT, editable=False) def sane_repr(*attrs: str, include_id=True) -> Callable[[object], str]: diff --git a/posthog/session_recordings/models/session_recording.py b/posthog/session_recordings/models/session_recording.py index 359df2faf94e7..be955e1981db9 100644 --- a/posthog/session_recordings/models/session_recording.py +++ b/posthog/session_recordings/models/session_recording.py @@ -27,33 +27,33 @@ class Meta: # https://github.com/PostHog/posthog-js/blob/e0dc2c005cfb5dd62b7c876676bcffe1654417a7/src/utils.ts#L457-L458 # We create recording objects with both UUIDT and a unique session_id field to remain backwards compatible. # All other models related to the session recording model uses this unique `session_id` to create the link. - session_id: models.CharField = models.CharField(unique=True, max_length=200) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, null=True, blank=True) - deleted: models.BooleanField = models.BooleanField(null=True, blank=True) - object_storage_path: models.CharField = models.CharField(max_length=200, null=True, blank=True) + session_id = models.CharField(unique=True, max_length=200) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True) + deleted = models.BooleanField(null=True, blank=True) + object_storage_path = models.CharField(max_length=200, null=True, blank=True) - distinct_id: models.CharField = models.CharField(max_length=400, null=True, blank=True) + distinct_id = models.CharField(max_length=400, null=True, blank=True) - duration: models.IntegerField = models.IntegerField(blank=True, null=True) - active_seconds: models.IntegerField = models.IntegerField(blank=True, null=True) - inactive_seconds: models.IntegerField = models.IntegerField(blank=True, null=True) - start_time: models.DateTimeField = models.DateTimeField(blank=True, null=True) - end_time: models.DateTimeField = models.DateTimeField(blank=True, null=True) + duration = models.IntegerField(blank=True, null=True) + active_seconds = models.IntegerField(blank=True, null=True) + inactive_seconds = models.IntegerField(blank=True, null=True) + start_time = models.DateTimeField(blank=True, null=True) + end_time = models.DateTimeField(blank=True, null=True) - click_count: models.IntegerField = models.IntegerField(blank=True, null=True) - keypress_count: models.IntegerField = models.IntegerField(blank=True, null=True) - mouse_activity_count: models.IntegerField = models.IntegerField(blank=True, null=True) + click_count = models.IntegerField(blank=True, null=True) + keypress_count = models.IntegerField(blank=True, null=True) + mouse_activity_count = models.IntegerField(blank=True, null=True) - console_log_count: models.IntegerField = models.IntegerField(blank=True, null=True) - console_warn_count: models.IntegerField = models.IntegerField(blank=True, null=True) - console_error_count: models.IntegerField = models.IntegerField(blank=True, null=True) + console_log_count = models.IntegerField(blank=True, null=True) + console_warn_count = models.IntegerField(blank=True, null=True) + console_error_count = models.IntegerField(blank=True, null=True) - start_url: models.CharField = models.CharField(blank=True, null=True, max_length=512) + start_url = models.CharField(blank=True, null=True, max_length=512) # we can't store storage version in the stored content # as we might need to know the version before knowing how to load the data - storage_version: models.CharField = models.CharField(blank=True, null=True, max_length=20) + storage_version = models.CharField(blank=True, null=True, max_length=20) # DYNAMIC FIELDS diff --git a/posthog/session_recordings/models/session_recording_event.py b/posthog/session_recordings/models/session_recording_event.py index 75f9a9c116251..c29c4db1ad781 100644 --- a/posthog/session_recordings/models/session_recording_event.py +++ b/posthog/session_recordings/models/session_recording_event.py @@ -15,13 +15,13 @@ class Meta: # models.Index(fields=["team_id", "timestamp"]), ] - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, null=True, blank=True) - timestamp: models.DateTimeField = models.DateTimeField(default=timezone.now, blank=True) - team: models.ForeignKey = models.ForeignKey(Team, on_delete=models.CASCADE) - distinct_id: models.CharField = models.CharField(max_length=200) - session_id: models.CharField = models.CharField(max_length=200) - window_id: models.CharField = models.CharField(max_length=200, null=True, blank=True) - snapshot_data: models.JSONField = models.JSONField(default=dict) + created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True) + timestamp = models.DateTimeField(default=timezone.now, blank=True) + team = models.ForeignKey(Team, on_delete=models.CASCADE) + distinct_id = models.CharField(max_length=200) + session_id = models.CharField(max_length=200) + window_id = models.CharField(max_length=200, null=True, blank=True) + snapshot_data = models.JSONField(default=dict) class SessionRecordingViewed(models.Model): @@ -29,7 +29,7 @@ class Meta: unique_together = (("team_id", "user_id", "session_id"),) indexes = [models.Index(fields=["team_id", "user_id", "session_id"])] - team: models.ForeignKey = models.ForeignKey(Team, on_delete=models.CASCADE) - user: models.ForeignKey = models.ForeignKey("User", on_delete=models.CASCADE) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, null=True, blank=True) - session_id: models.CharField = models.CharField(max_length=200) + team = models.ForeignKey(Team, on_delete=models.CASCADE) + user = models.ForeignKey("User", on_delete=models.CASCADE) + created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True) + session_id = models.CharField(max_length=200) diff --git a/posthog/session_recordings/models/session_recording_playlist.py b/posthog/session_recordings/models/session_recording_playlist.py index 9c198dbd83e3c..4a272249519a6 100644 --- a/posthog/session_recordings/models/session_recording_playlist.py +++ b/posthog/session_recordings/models/session_recording_playlist.py @@ -5,18 +5,18 @@ class SessionRecordingPlaylist(models.Model): - short_id: models.CharField = models.CharField(max_length=12, blank=True, default=generate_short_id) - name: models.CharField = models.CharField(max_length=400, null=True, blank=True) - derived_name: models.CharField = models.CharField(max_length=400, null=True, blank=True) - description: models.TextField = models.TextField(blank=True) - team: models.ForeignKey = models.ForeignKey("Team", on_delete=models.CASCADE) - pinned: models.BooleanField = models.BooleanField(default=False) - deleted: models.BooleanField = models.BooleanField(default=False) - filters: models.JSONField = models.JSONField(default=dict) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) - created_by: models.ForeignKey = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) - last_modified_at: models.DateTimeField = models.DateTimeField(default=timezone.now) - last_modified_by: models.ForeignKey = models.ForeignKey( + short_id = models.CharField(max_length=12, blank=True, default=generate_short_id) + name = models.CharField(max_length=400, null=True, blank=True) + derived_name = models.CharField(max_length=400, null=True, blank=True) + description = models.TextField(blank=True) + team = models.ForeignKey("Team", on_delete=models.CASCADE) + pinned = models.BooleanField(default=False) + deleted = models.BooleanField(default=False) + filters = models.JSONField(default=dict) + created_at = models.DateTimeField(auto_now_add=True, blank=True) + created_by = models.ForeignKey("User", on_delete=models.SET_NULL, null=True, blank=True) + last_modified_at = models.DateTimeField(default=timezone.now) + last_modified_by = models.ForeignKey( "User", on_delete=models.SET_NULL, null=True, @@ -25,7 +25,7 @@ class SessionRecordingPlaylist(models.Model): ) # DEPRECATED - is_static: models.BooleanField = models.BooleanField(default=False) + is_static = models.BooleanField(default=False) # Changing these fields materially alters the Playlist, so these count for the "last_modified_*" fields MATERIAL_PLAYLIST_FIELDS = {"name", "description", "filters"} diff --git a/posthog/session_recordings/models/session_recording_playlist_item.py b/posthog/session_recordings/models/session_recording_playlist_item.py index 73d38815fdef8..bed57e0e6b4ed 100644 --- a/posthog/session_recordings/models/session_recording_playlist_item.py +++ b/posthog/session_recordings/models/session_recording_playlist_item.py @@ -5,7 +5,7 @@ class SessionRecordingPlaylistItem(models.Model): class Meta: unique_together = ("recording", "playlist") - recording: models.ForeignKey = models.ForeignKey( + recording = models.ForeignKey( "SessionRecording", related_name="playlist_items", on_delete=models.CASCADE, @@ -13,14 +13,14 @@ class Meta: null=True, blank=True, ) - playlist: models.ForeignKey = models.ForeignKey( + playlist = models.ForeignKey( "SessionRecordingPlaylist", related_name="playlist_items", on_delete=models.CASCADE, ) - created_at: models.DateTimeField = models.DateTimeField(auto_now_add=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True, blank=True) # DEPRECATED: We hard delete as this is only a joiner table - deleted: models.BooleanField = models.BooleanField(null=True, blank=True) + deleted = models.BooleanField(null=True, blank=True) # DEPRECATED: Use recording_id instead - session_id: models.CharField = models.CharField(max_length=200, null=True, blank=True) + session_id = models.CharField(max_length=200, null=True, blank=True) diff --git a/posthog/warehouse/models/credential.py b/posthog/warehouse/models/credential.py index 0be74816459d8..39828f51898d8 100644 --- a/posthog/warehouse/models/credential.py +++ b/posthog/warehouse/models/credential.py @@ -9,7 +9,7 @@ class DataWarehouseCredential(CreatedMetaFields, UUIDModel): access_key: EncryptedTextField = EncryptedTextField(max_length=500) access_secret: EncryptedTextField = EncryptedTextField(max_length=500) - team: models.ForeignKey = models.ForeignKey(Team, on_delete=models.CASCADE) + team = models.ForeignKey(Team, on_delete=models.CASCADE) __repr__ = sane_repr("access_key") diff --git a/posthog/warehouse/models/datawarehouse_saved_query.py b/posthog/warehouse/models/datawarehouse_saved_query.py index 204a85c15f80f..e3cccac60488b 100644 --- a/posthog/warehouse/models/datawarehouse_saved_query.py +++ b/posthog/warehouse/models/datawarehouse_saved_query.py @@ -37,18 +37,16 @@ def validate_saved_query_name(value): class DataWarehouseSavedQuery(CreatedMetaFields, UUIDModel, DeletedMetaFields): - name: models.CharField = models.CharField(max_length=128, validators=[validate_saved_query_name]) - team: models.ForeignKey = models.ForeignKey(Team, on_delete=models.CASCADE) - columns: models.JSONField = models.JSONField( + name = models.CharField(max_length=128, validators=[validate_saved_query_name]) + team = models.ForeignKey(Team, on_delete=models.CASCADE) + columns = models.JSONField( default=dict, null=True, blank=True, help_text="Dict of all columns with ClickHouse type (including Nullable())", ) - external_tables: models.JSONField = models.JSONField( - default=list, null=True, blank=True, help_text="List of all external tables" - ) - query: models.JSONField = models.JSONField(default=dict, null=True, blank=True, help_text="HogQL query") + external_tables = models.JSONField(default=list, null=True, blank=True, help_text="List of all external tables") + query = models.JSONField(default=dict, null=True, blank=True, help_text="HogQL query") class Meta: constraints = [ diff --git a/posthog/warehouse/models/external_data_job.py b/posthog/warehouse/models/external_data_job.py index 7b7f1cc15e1a8..3b85c70029405 100644 --- a/posthog/warehouse/models/external_data_job.py +++ b/posthog/warehouse/models/external_data_job.py @@ -16,21 +16,15 @@ class Status(models.TextChoices): COMPLETED = "Completed", "Completed" CANCELLED = "Cancelled", "Cancelled" - team: models.ForeignKey = models.ForeignKey(Team, on_delete=models.CASCADE) - pipeline: models.ForeignKey = models.ForeignKey( - "posthog.ExternalDataSource", related_name="jobs", on_delete=models.CASCADE - ) - schema: models.ForeignKey = models.ForeignKey( - "posthog.ExternalDataSchema", on_delete=models.CASCADE, null=True, blank=True - ) - status: models.CharField = models.CharField(max_length=400) - rows_synced: models.BigIntegerField = models.BigIntegerField(null=True, blank=True) - latest_error: models.TextField = models.TextField( - null=True, help_text="The latest error that occurred during this run." - ) - - workflow_id: models.CharField = models.CharField(max_length=400, null=True, blank=True) - workflow_run_id: models.CharField = models.CharField(max_length=400, null=True, blank=True) + team = models.ForeignKey(Team, on_delete=models.CASCADE) + pipeline = models.ForeignKey("posthog.ExternalDataSource", related_name="jobs", on_delete=models.CASCADE) + schema = models.ForeignKey("posthog.ExternalDataSchema", on_delete=models.CASCADE, null=True, blank=True) + status = models.CharField(max_length=400) + rows_synced = models.BigIntegerField(null=True, blank=True) + latest_error = models.TextField(null=True, help_text="The latest error that occurred during this run.") + + workflow_id = models.CharField(max_length=400, null=True, blank=True) + workflow_run_id = models.CharField(max_length=400, null=True, blank=True) __repr__ = sane_repr("id") diff --git a/posthog/warehouse/models/external_data_schema.py b/posthog/warehouse/models/external_data_schema.py index 8306f3468fb8b..f42cf3248b8ad 100644 --- a/posthog/warehouse/models/external_data_schema.py +++ b/posthog/warehouse/models/external_data_schema.py @@ -38,22 +38,16 @@ class SyncFrequency(models.TextChoices): WEEKLY = "week", "Weekly" MONTHLY = "month", "Monthly" - name: models.CharField = models.CharField(max_length=400) - team: models.ForeignKey = models.ForeignKey(Team, on_delete=models.CASCADE) - source: models.ForeignKey = models.ForeignKey( - "posthog.ExternalDataSource", related_name="schemas", on_delete=models.CASCADE - ) - table: models.ForeignKey = models.ForeignKey( - "posthog.DataWarehouseTable", on_delete=models.SET_NULL, null=True, blank=True - ) - should_sync: models.BooleanField = models.BooleanField(default=True) - latest_error: models.TextField = models.TextField( - null=True, help_text="The latest error that occurred when syncing this schema." - ) - status: models.CharField = models.CharField(max_length=400, null=True, blank=True) - last_synced_at: models.DateTimeField = models.DateTimeField(null=True, blank=True) - sync_type: models.CharField = models.CharField(max_length=128, choices=SyncType.choices, null=True, blank=True) - sync_type_config: models.JSONField = models.JSONField( + name = models.CharField(max_length=400) + team = models.ForeignKey(Team, on_delete=models.CASCADE) + source = models.ForeignKey("posthog.ExternalDataSource", related_name="schemas", on_delete=models.CASCADE) + table = models.ForeignKey("posthog.DataWarehouseTable", on_delete=models.SET_NULL, null=True, blank=True) + should_sync = models.BooleanField(default=True) + latest_error = models.TextField(null=True, help_text="The latest error that occurred when syncing this schema.") + status = models.CharField(max_length=400, null=True, blank=True) + last_synced_at = models.DateTimeField(null=True, blank=True) + sync_type = models.CharField(max_length=128, choices=SyncType.choices, null=True, blank=True) + sync_type_config = models.JSONField( default=dict, blank=True, ) @@ -61,9 +55,7 @@ class SyncFrequency(models.TextChoices): sync_frequency = deprecate_field( models.CharField(max_length=128, choices=SyncFrequency.choices, default=SyncFrequency.DAILY, blank=True) ) - sync_frequency_interval: models.DurationField = models.DurationField( - default=timedelta(hours=6), null=True, blank=True - ) + sync_frequency_interval = models.DurationField(default=timedelta(hours=6), null=True, blank=True) __repr__ = sane_repr("name") diff --git a/posthog/warehouse/models/external_data_source.py b/posthog/warehouse/models/external_data_source.py index 9ddd407f03fef..49c91d7781764 100644 --- a/posthog/warehouse/models/external_data_source.py +++ b/posthog/warehouse/models/external_data_source.py @@ -37,24 +37,24 @@ class SyncFrequency(models.TextChoices): MONTHLY = "month", "Monthly" # TODO provide flexible schedule definition - source_id: models.CharField = models.CharField(max_length=400) - connection_id: models.CharField = models.CharField(max_length=400) - destination_id: models.CharField = models.CharField(max_length=400, null=True, blank=True) - team: models.ForeignKey = models.ForeignKey(Team, on_delete=models.CASCADE) + source_id = models.CharField(max_length=400) + connection_id = models.CharField(max_length=400) + destination_id = models.CharField(max_length=400, null=True, blank=True) + team = models.ForeignKey(Team, on_delete=models.CASCADE) # Deprecated, use `ExternalDataSchema.sync_frequency_interval` - sync_frequency: models.CharField = models.CharField( + sync_frequency = models.CharField( max_length=128, choices=SyncFrequency.choices, default=SyncFrequency.DAILY, blank=True ) # `status` is deprecated in favour of external_data_schema.status - status: models.CharField = models.CharField(max_length=400) - source_type: models.CharField = models.CharField(max_length=128, choices=Type.choices) + status = models.CharField(max_length=400) + source_type = models.CharField(max_length=128, choices=Type.choices) job_inputs: encrypted_fields.fields.EncryptedJSONField = encrypted_fields.fields.EncryptedJSONField( null=True, blank=True ) - are_tables_created: models.BooleanField = models.BooleanField(default=False) - prefix: models.CharField = models.CharField(max_length=100, null=True, blank=True) + are_tables_created = models.BooleanField(default=False) + prefix = models.CharField(max_length=100, null=True, blank=True) __repr__ = sane_repr("id") diff --git a/posthog/warehouse/models/join.py b/posthog/warehouse/models/join.py index b6438cc294fb4..000b1ba34f9b2 100644 --- a/posthog/warehouse/models/join.py +++ b/posthog/warehouse/models/join.py @@ -26,20 +26,20 @@ def __init__(self, *args, **kwargs): warn("DataWarehouseViewLink is deprecated, use DataWarehouseJoin", DeprecationWarning, stacklevel=2) super().__init__(*args, **kwargs) - team: models.ForeignKey = models.ForeignKey(Team, on_delete=models.CASCADE) - table: models.CharField = models.CharField(max_length=128) - from_join_key: models.CharField = models.CharField(max_length=400) - saved_query: models.ForeignKey = models.ForeignKey(DataWarehouseSavedQuery, on_delete=models.CASCADE) - to_join_key: models.CharField = models.CharField(max_length=400) + team = models.ForeignKey(Team, on_delete=models.CASCADE) + table = models.CharField(max_length=128) + from_join_key = models.CharField(max_length=400) + saved_query = models.ForeignKey(DataWarehouseSavedQuery, on_delete=models.CASCADE) + to_join_key = models.CharField(max_length=400) class DataWarehouseJoin(CreatedMetaFields, UUIDModel, DeletedMetaFields): - team: models.ForeignKey = models.ForeignKey(Team, on_delete=models.CASCADE) - source_table_name: models.CharField = models.CharField(max_length=400) - source_table_key: models.CharField = models.CharField(max_length=400) - joining_table_name: models.CharField = models.CharField(max_length=400) - joining_table_key: models.CharField = models.CharField(max_length=400) - field_name: models.CharField = models.CharField(max_length=400) + team = models.ForeignKey(Team, on_delete=models.CASCADE) + source_table_name = models.CharField(max_length=400) + source_table_key = models.CharField(max_length=400) + joining_table_name = models.CharField(max_length=400) + joining_table_key = models.CharField(max_length=400) + field_name = models.CharField(max_length=400) def join_function( self, override_source_table_key: Optional[str] = None, override_joining_table_key: Optional[str] = None diff --git a/posthog/warehouse/models/table.py b/posthog/warehouse/models/table.py index a742abc79aaa3..f2ebec5239fd6 100644 --- a/posthog/warehouse/models/table.py +++ b/posthog/warehouse/models/table.py @@ -81,29 +81,23 @@ class TableFormat(models.TextChoices): Delta = "Delta", "Delta" DeltaS3Wrapper = "DeltaS3Wrapper", "DeltaS3Wrapper" - name: models.CharField = models.CharField(max_length=128) - format: models.CharField = models.CharField(max_length=128, choices=TableFormat.choices) - team: models.ForeignKey = models.ForeignKey(Team, on_delete=models.CASCADE) + name = models.CharField(max_length=128) + format = models.CharField(max_length=128, choices=TableFormat.choices) + team = models.ForeignKey(Team, on_delete=models.CASCADE) - url_pattern: models.CharField = models.CharField(max_length=500) - credential: models.ForeignKey = models.ForeignKey( - DataWarehouseCredential, on_delete=models.CASCADE, null=True, blank=True - ) + url_pattern = models.CharField(max_length=500) + credential = models.ForeignKey(DataWarehouseCredential, on_delete=models.CASCADE, null=True, blank=True) - external_data_source: models.ForeignKey = models.ForeignKey( - "ExternalDataSource", on_delete=models.CASCADE, null=True, blank=True - ) + external_data_source = models.ForeignKey("ExternalDataSource", on_delete=models.CASCADE, null=True, blank=True) - columns: models.JSONField = models.JSONField( + columns = models.JSONField( default=dict, null=True, blank=True, help_text="Dict of all columns with Clickhouse type (including Nullable())", ) - row_count: models.IntegerField = models.IntegerField( - null=True, help_text="How many rows are currently synced in this table" - ) + row_count = models.IntegerField(null=True, help_text="How many rows are currently synced in this table") __repr__ = sane_repr("name") diff --git a/pyproject.toml b/pyproject.toml index bcc0010614943..39ae66d04c235 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,7 @@ select = [ "B", "C4", "C9", - "DJ012", + # "DJ012", TODO: Re-enable this "E", "F", "RUF005", diff --git a/requirements-dev.in b/requirements-dev.in index d76b0a055cb86..8ab3ba93b3a2d 100644 --- a/requirements-dev.in +++ b/requirements-dev.in @@ -17,7 +17,7 @@ mypy-baseline~=0.7.0 mypy-extensions==1.0.0 datamodel-code-generator==0.25.6 djangorestframework-stubs~=3.14.5 -django-stubs==4.2.7 +django-stubs==5.0.4 Faker==17.5.0 fakeredis[lua]==2.23.3 freezegun==1.2.2 diff --git a/requirements-dev.txt b/requirements-dev.txt index e61940bab377d..277f8c9ceb44f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -75,11 +75,9 @@ django==4.2.14 # -c requirements.txt # django-stubs # django-stubs-ext -django-stubs==4.2.7 - # via - # -r requirements-dev.in - # djangorestframework-stubs -django-stubs-ext==5.0.0 +django-stubs==5.0.4 + # via djangorestframework-stubs +django-stubs-ext==5.0.4 # via django-stubs djangorestframework-stubs==3.14.5 # via -r requirements-dev.in @@ -282,8 +280,7 @@ ruamel-yaml==0.18.6 # via prance ruamel-yaml-clib==0.2.8 # via ruamel-yaml -ruff==0.4.10 - # via -r requirements-dev.in +ruff==0.6.1 six==1.16.0 # via # -c requirements.txt @@ -342,7 +339,7 @@ types-toml==0.10.8.20240310 # via inline-snapshot types-tzlocal==5.1.0.1 # via -r requirements-dev.in -typing-extensions==4.7.1 +typing-extensions==4.12.2 # via # -c requirements.txt # boto3-stubs diff --git a/requirements.txt b/requirements.txt index 151cbcfb2007f..4e887d218f265 100644 --- a/requirements.txt +++ b/requirements.txt @@ -660,7 +660,7 @@ types-protobuf==4.22.0.0 # via temporalio types-setuptools==69.0.0.0 # via requirements-parser -typing-extensions==4.7.1 +typing-extensions==4.12.2 # via # dlt # openai From 4f483685fa95067a6768d820769ee70cde6a4a6a Mon Sep 17 00:00:00 2001 From: Julian Bez Date: Wed, 21 Aug 2024 13:00:14 +0200 Subject: [PATCH 3/6] Fix activity_log --- posthog/models/activity_logging/activity_log.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/posthog/models/activity_logging/activity_log.py b/posthog/models/activity_logging/activity_log.py index 5b3bec4ad7536..82c13105f1ebb 100644 --- a/posthog/models/activity_logging/activity_log.py +++ b/posthog/models/activity_logging/activity_log.py @@ -434,8 +434,7 @@ class ActivityPage: results: list[ActivityLog] -def get_activity_page(activity_query=10, page: int = 1) -> ActivityPage: - limit = 100 +def get_activity_page(activity_query: models.QuerySet, limit: int = 10, page: int = 1) -> ActivityPage: paginator = Paginator(activity_query, limit) activity_page = paginator.page(page) From 8a4d16087fc1fbb5767a6a5ea3b25a5b6bb990c3 Mon Sep 17 00:00:00 2001 From: Julian Bez Date: Wed, 21 Aug 2024 13:04:31 +0200 Subject: [PATCH 4/6] Fix baseline --- mypy-baseline.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 7a560db891885..a5cc892fa8722 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -229,10 +229,6 @@ posthog/models/feature_flag/flag_matching.py:0: error: Value of type variable "_ posthog/models/feature_flag/flag_matching.py:0: error: Value of type variable "_E" of "ExpressionWrapper" cannot be "object" [type-var] posthog/models/feature_flag/flag_matching.py:0: error: Argument 1 to "get" of "dict" has incompatible type "str | None"; expected "str" [arg-type] posthog/models/feature_flag/flag_matching.py:0: error: Value of type variable "_E" of "ExpressionWrapper" cannot be "object" [type-var] -posthog/models/activity_logging/activity_log.py:0: error: Name "limit" is not defined [name-defined] -posthog/models/activity_logging/activity_log.py:0: error: Name "limit" is not defined [name-defined] -posthog/models/activity_logging/activity_log.py:0: error: Too many arguments for "get_activity_page" [call-arg] -posthog/models/activity_logging/activity_log.py:0: error: Too many arguments for "get_activity_page" [call-arg] posthog/hogql/printer.py:0: error: Argument 1 to "create_hogql_database" has incompatible type "int | None"; expected "int" [arg-type] posthog/hogql/printer.py:0: error: List comprehension has incompatible type List[SelectQueryType | None]; expected List[SelectQueryType] [misc] posthog/hogql/printer.py:0: error: Argument "stack" to "_Printer" has incompatible type "list[SelectQuery]"; expected "list[AST] | None" [arg-type] From 542ccb5d50390aba5d639519644aa36a3064396d Mon Sep 17 00:00:00 2001 From: Julian Bez Date: Thu, 22 Aug 2024 07:57:08 +0200 Subject: [PATCH 5/6] Fix test_timings lint issue --- posthog/hogql/test/test_timings.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/posthog/hogql/test/test_timings.py b/posthog/hogql/test/test_timings.py index cfb2259157afa..6e01180e7a62a 100644 --- a/posthog/hogql/test/test_timings.py +++ b/posthog/hogql/test/test_timings.py @@ -15,9 +15,6 @@ class TestHogQLTimings(BaseTest): def setUp(self): counter_values[0] = 0 - def assertAlmostEquals(self, a, b, epsilon=EPSILON): - self.assertTrue(abs(a - b) < epsilon, f"{a} != {b} within {epsilon}") - def test_basic_timing(self): with patch("posthog.hogql.timings.perf_counter", fake_perf_counter): timings = HogQLTimings() From c233bb356499720c86b6ee88cb6a14a4c0e9995e Mon Sep 17 00:00:00 2001 From: Julian Bez Date: Thu, 22 Aug 2024 10:03:34 +0200 Subject: [PATCH 6/6] Fix --- mypy-baseline.txt | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/mypy-baseline.txt b/mypy-baseline.txt index a5cc892fa8722..bf03484babdbf 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -494,18 +494,6 @@ posthog/hogql/test/test_timings.py:0: error: No overload variant of "__setitem__ posthog/hogql/test/test_timings.py:0: note: Possible overload variants: posthog/hogql/test/test_timings.py:0: note: def __setitem__(self, SupportsIndex, int, /) -> None posthog/hogql/test/test_timings.py:0: note: def __setitem__(self, slice, Iterable[int], /) -> None -posthog/hogql/test/test_timings.py:0: error: Signature of "assertAlmostEquals" incompatible with supertype "TestCase" [override] -posthog/hogql/test/test_timings.py:0: note: Superclass: -posthog/hogql/test/test_timings.py:0: note: @overload -posthog/hogql/test/test_timings.py:0: note: def [_S: SupportsSub[Any, Any]] (self: TestCase, first: _S, second: _S, places: None, msg: Any, delta: _SupportsAbsAndDunderGE) -> None -posthog/hogql/test/test_timings.py:0: note: @overload -posthog/hogql/test/test_timings.py:0: note: def [_S: SupportsSub[Any, Any]] (self: TestCase, first: _S, second: _S, places: None = ..., msg: Any = ..., *, delta: _SupportsAbsAndDunderGE) -> None -posthog/hogql/test/test_timings.py:0: note: @overload -posthog/hogql/test/test_timings.py:0: note: def [_T] (self: TestCase, first: SupportsSub[_T, SupportsAbs[SupportsRound[object]]], second: _T, places: int | None = ..., msg: Any = ..., delta: None = ...) -> None -posthog/hogql/test/test_timings.py:0: note: @overload -posthog/hogql/test/test_timings.py:0: note: def [_T] (self: TestCase, first: _T, second: SupportsRSub[_T, SupportsAbs[SupportsRound[object]]], places: int | None = ..., msg: Any = ..., delta: None = ...) -> None -posthog/hogql/test/test_timings.py:0: note: Subclass: -posthog/hogql/test/test_timings.py:0: note: def assertAlmostEquals(self, a: Any, b: Any, epsilon: Any = ...) -> Any posthog/hogql/test/test_resolver.py:0: error: Item "None" of "JoinExpr | None" has no attribute "next_join" [union-attr] posthog/hogql/test/test_resolver.py:0: error: Item "None" of "JoinExpr | Any | None" has no attribute "constraint" [union-attr] posthog/hogql/test/test_resolver.py:0: error: Item "None" of "JoinConstraint | Any | None" has no attribute "constraint_type" [union-attr]