From 013ea270b160d7913b12d46fb228c7dbfc901f70 Mon Sep 17 00:00:00 2001 From: Tom Owers Date: Wed, 4 Dec 2024 18:01:54 +0000 Subject: [PATCH 1/3] Allow key pair auth for snowflake sources --- .../data-warehouse/new/sourceWizardLogic.tsx | 64 ++++++++++++++--- .../pipelines/sql_database/__init__.py | 60 ++++++++++++---- .../pipelines/sql_database_v2/__init__.py | 60 ++++++++++++---- .../workflow_activities/import_data_sync.py | 15 ++-- .../workflow_activities/sync_new_schemas.py | 21 +++++- posthog/warehouse/api/external_data_source.py | 71 +++++++++++++++---- .../warehouse/models/external_data_schema.py | 40 +++++++++-- 7 files changed, 273 insertions(+), 58 deletions(-) diff --git a/frontend/src/scenes/data-warehouse/new/sourceWizardLogic.tsx b/frontend/src/scenes/data-warehouse/new/sourceWizardLogic.tsx index a924b0ba594b7..f8e1a5a131205 100644 --- a/frontend/src/scenes/data-warehouse/new/sourceWizardLogic.tsx +++ b/frontend/src/scenes/data-warehouse/new/sourceWizardLogic.tsx @@ -513,18 +513,60 @@ export const SOURCE_DETAILS: Record = { placeholder: 'COMPUTE_WAREHOUSE', }, { - name: 'user', - label: 'User', - type: 'text', - required: true, - placeholder: 'user', - }, - { - name: 'password', - label: 'Password', - type: 'password', + type: 'select', + name: 'auth_type', + label: 'Authentication type', required: true, - placeholder: '', + defaultValue: 'password', + options: [ + { + label: 'Password', + value: 'password', + fields: [ + { + name: 'username', + label: 'Username', + type: 'text', + required: true, + placeholder: 'User1', + }, + { + name: 'password', + label: 'Password', + type: 'password', + required: true, + placeholder: '', + }, + ], + }, + { + label: 'Key pair', + value: 'keypair', + fields: [ + { + name: 'username', + label: 'Username', + type: 'text', + required: true, + placeholder: 'User1', + }, + { + name: 'private_key', + label: 'Private key', + type: 'textarea', + required: true, + placeholder: '', + }, + { + name: 'passphrase', + label: 'Passphrase', + type: 'password', + required: false, + placeholder: '', + }, + ], + }, + ], }, { name: 'role', diff --git a/posthog/temporal/data_imports/pipelines/sql_database/__init__.py b/posthog/temporal/data_imports/pipelines/sql_database/__init__.py index fbf6a0ee01683..04aa7c9678c0b 100644 --- a/posthog/temporal/data_imports/pipelines/sql_database/__init__.py +++ b/posthog/temporal/data_imports/pipelines/sql_database/__init__.py @@ -21,6 +21,9 @@ from posthog.warehouse.models.external_data_source import ExternalDataSource from sqlalchemy.sql import text +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import serialization + from .helpers import ( table_rows, engine_from_credentials, @@ -109,8 +112,11 @@ def sql_source_for_type( def snowflake_source( account_id: str, - user: str, - password: str, + user: Optional[str], + password: Optional[str], + passphrase: Optional[str], + private_key: Optional[str], + auth_type: str, database: str, warehouse: str, schema: str, @@ -119,13 +125,6 @@ def snowflake_source( incremental_field: Optional[str] = None, incremental_field_type: Optional[IncrementalFieldType] = None, ) -> DltSource: - account_id = quote(account_id) - user = quote(user) - password = quote(password) - database = quote(database) - warehouse = quote(warehouse) - role = quote(role) if role else None - if incremental_field is not None and incremental_field_type is not None: incremental: dlt.sources.incremental | None = dlt.sources.incremental( cursor_path=incremental_field, initial_value=incremental_type_to_initial_value(incremental_field_type) @@ -133,9 +132,46 @@ def snowflake_source( else: incremental = None - credentials = ConnectionStringCredentials( - f"snowflake://{user}:{password}@{account_id}/{database}/{schema}?warehouse={warehouse}{f'&role={role}' if role else ''}" - ) + if auth_type == "password" and user is not None and password is not None: + account_id = quote(account_id) + user = quote(user) + password = quote(password) + database = quote(database) + warehouse = quote(warehouse) + role = quote(role) if role else None + + credentials = create_engine( + f"snowflake://{user}:{password}@{account_id}/{database}/{schema}?warehouse={warehouse}{f'&role={role}' if role else ''}" + ) + else: + assert private_key is not None + assert user is not None + + account_id = quote(account_id) + user = quote(user) + database = quote(database) + warehouse = quote(warehouse) + role = quote(role) if role else None + + p_key = serialization.load_pem_private_key( + private_key.encode("utf-8"), + password=passphrase.encode() if passphrase is not None else None, + backend=default_backend(), + ) + + pkb = p_key.private_bytes( + encoding=serialization.Encoding.DER, + format=serialization.PrivateFormat.PKCS8, + encryption_algorithm=serialization.NoEncryption(), + ) + + credentials = create_engine( + f"snowflake://{user}@{account_id}/{database}/{schema}?warehouse={warehouse}{f'&role={role}' if role else ''}", + connect_args={ + "private_key": pkb, + }, + ) + db_source = sql_database(credentials, schema=schema, table_names=table_names, incremental=incremental) return db_source diff --git a/posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py b/posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py index cfd5f4cb822c0..bcab4c3e19282 100644 --- a/posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py +++ b/posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py @@ -20,6 +20,9 @@ from posthog.warehouse.models import ExternalDataSource from posthog.warehouse.types import IncrementalFieldType +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import serialization + from .helpers import ( SelectAny, table_rows, @@ -125,8 +128,11 @@ def sql_source_for_type( def snowflake_source( account_id: str, - user: str, - password: str, + user: Optional[str], + password: Optional[str], + passphrase: Optional[str], + private_key: Optional[str], + auth_type: str, database: str, warehouse: str, schema: str, @@ -135,13 +141,6 @@ def snowflake_source( incremental_field: Optional[str] = None, incremental_field_type: Optional[IncrementalFieldType] = None, ) -> DltSource: - account_id = quote(account_id) - user = quote(user) - password = quote(password) - database = quote(database) - warehouse = quote(warehouse) - role = quote(role) if role else None - if incremental_field is not None and incremental_field_type is not None: incremental: dlt.sources.incremental | None = dlt.sources.incremental( cursor_path=incremental_field, initial_value=incremental_type_to_initial_value(incremental_field_type) @@ -149,9 +148,46 @@ def snowflake_source( else: incremental = None - credentials = ConnectionStringCredentials( - f"snowflake://{user}:{password}@{account_id}/{database}/{schema}?warehouse={warehouse}{f'&role={role}' if role else ''}" - ) + if auth_type == "password" and user is not None and password is not None: + account_id = quote(account_id) + user = quote(user) + password = quote(password) + database = quote(database) + warehouse = quote(warehouse) + role = quote(role) if role else None + + credentials = create_engine( + f"snowflake://{user}:{password}@{account_id}/{database}/{schema}?warehouse={warehouse}{f'&role={role}' if role else ''}" + ) + else: + assert private_key is not None + assert user is not None + + account_id = quote(account_id) + user = quote(user) + database = quote(database) + warehouse = quote(warehouse) + role = quote(role) if role else None + + p_key = serialization.load_pem_private_key( + private_key.encode("utf-8"), + password=passphrase.encode() if passphrase is not None else None, + backend=default_backend(), + ) + + pkb = p_key.private_bytes( + encoding=serialization.Encoding.DER, + format=serialization.PrivateFormat.PKCS8, + encryption_algorithm=serialization.NoEncryption(), + ) + + credentials = create_engine( + f"snowflake://{user}@{account_id}/{database}/{schema}?warehouse={warehouse}{f'&role={role}' if role else ''}", + connect_args={ + "private_key": pkb, + }, + ) + db_source = sql_database(credentials, schema=schema, table_names=table_names, incremental=incremental) return db_source diff --git a/posthog/temporal/data_imports/workflow_activities/import_data_sync.py b/posthog/temporal/data_imports/workflow_activities/import_data_sync.py index 091828d34ba52..eeaf3b9f65de1 100644 --- a/posthog/temporal/data_imports/workflow_activities/import_data_sync.py +++ b/posthog/temporal/data_imports/workflow_activities/import_data_sync.py @@ -228,17 +228,24 @@ def import_data_activity_sync(inputs: ImportDataActivityInputs): ) account_id = model.pipeline.job_inputs.get("account_id") - user = model.pipeline.job_inputs.get("user") - password = model.pipeline.job_inputs.get("password") database = model.pipeline.job_inputs.get("database") warehouse = model.pipeline.job_inputs.get("warehouse") sf_schema = model.pipeline.job_inputs.get("schema") role = model.pipeline.job_inputs.get("role") + auth_type = model.pipeline.job_inputs.get("auth_type", "password") + auth_type_username = model.pipeline.job_inputs.get("user") + auth_type_password = model.pipeline.job_inputs.get("password") + auth_type_passphrase = model.pipeline.job_inputs.get("passphrase") + auth_type_private_key = model.pipeline.job_inputs.get("private_key") + source = snowflake_source( account_id=account_id, - user=user, - password=password, + auth_type=auth_type, + user=auth_type_username, + password=auth_type_password, + private_key=auth_type_private_key, + passphrase=auth_type_passphrase, database=database, schema=sf_schema, warehouse=warehouse, diff --git a/posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py b/posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py index 67f8c820e2837..b63d7ea869e16 100644 --- a/posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py +++ b/posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py @@ -86,14 +86,29 @@ def sync_new_schemas_activity(inputs: SyncNewSchemasActivityInputs) -> None: return account_id = source.job_inputs.get("account_id") - user = source.job_inputs.get("user") - password = source.job_inputs.get("password") database = source.job_inputs.get("database") warehouse = source.job_inputs.get("warehouse") sf_schema = source.job_inputs.get("schema") role = source.job_inputs.get("role") - sql_schemas = get_snowflake_schemas(account_id, database, warehouse, user, password, sf_schema, role) + auth_type = source.job_inputs.get("auth_type", "password") + auth_type_username = source.job_inputs.get("user") + auth_type_password = source.job_inputs.get("password") + auth_type_passphrase = source.job_inputs.get("passphrase") + auth_type_private_key = source.job_inputs.get("private_key") + + sql_schemas = get_snowflake_schemas( + account_id=account_id, + database=database, + warehouse=warehouse, + user=auth_type_username, + password=auth_type_password, + schema=sf_schema, + role=role, + auth_type=auth_type, + passphrase=auth_type_passphrase, + private_key=auth_type_private_key, + ) schemas_to_sync = list(sql_schemas.keys()) else: diff --git a/posthog/warehouse/api/external_data_source.py b/posthog/warehouse/api/external_data_source.py index cc1f38170d327..448c06533bf19 100644 --- a/posthog/warehouse/api/external_data_source.py +++ b/posthog/warehouse/api/external_data_source.py @@ -640,10 +640,15 @@ def _handle_snowflake_source( database = payload.get("database") warehouse = payload.get("warehouse") role = payload.get("role") - user = payload.get("user") - password = payload.get("password") schema = payload.get("schema") + auth_type_obj = payload.get("auth_type", {}) + auth_type = auth_type_obj.get("selection", None) + auth_type_username = auth_type_obj.get("username", None) + auth_type_password = auth_type_obj.get("password", None) + auth_type_passphrase = auth_type_obj.get("passphrase", None) + auth_type_private_key = auth_type_obj.get("private_key", None) + new_source_model = ExternalDataSource.objects.create( source_id=str(uuid.uuid4()), connection_id=str(uuid.uuid4()), @@ -656,14 +661,28 @@ def _handle_snowflake_source( "database": database, "warehouse": warehouse, "role": role, - "user": user, - "password": password, "schema": schema, + "auth_type": auth_type, + "user": auth_type_username, + "password": auth_type_password, + "passphrase": auth_type_passphrase, + "private_key": auth_type_private_key, }, prefix=prefix, ) - schemas = get_snowflake_schemas(account_id, database, warehouse, user, password, schema, role) + schemas = get_snowflake_schemas( + account_id=account_id, + database=database, + warehouse=warehouse, + user=auth_type_username, + password=auth_type_password, + schema=schema, + role=role, + passphrase=auth_type_passphrase, + private_key=auth_type_private_key, + auth_type=auth_type, + ) return new_source_model, list(schemas.keys()) @@ -1068,20 +1087,48 @@ def database_schema(self, request: Request, *arg: Any, **kwargs: Any): database = request.data.get("database") warehouse = request.data.get("warehouse") role = request.data.get("role") - user = request.data.get("user") - password = request.data.get("password") schema = request.data.get("schema") - if not account_id or not warehouse or not database or not user or not password or not schema: + auth_type_obj = request.data.get("auth_type", {}) + auth_type = auth_type_obj.get("selection", None) + auth_type_username = auth_type_obj.get("username", None) + auth_type_password = auth_type_obj.get("password", None) + auth_type_passphrase = auth_type_obj.get("passphrase", None) + auth_type_private_key = auth_type_obj.get("private_key", None) + + if not account_id or not warehouse or not database or not schema: + return Response( + status=status.HTTP_400_BAD_REQUEST, + data={"message": "Missing required parameters: account id, warehouse, database, schema"}, + ) + + if auth_type == "password" and (not auth_type_username or not auth_type_password): + return Response( + status=status.HTTP_400_BAD_REQUEST, + data={"message": "Missing required parameters: username, password"}, + ) + + if auth_type == "keypair" and ( + not auth_type_passphrase or not auth_type_private_key or not auth_type_username + ): return Response( status=status.HTTP_400_BAD_REQUEST, - data={ - "message": "Missing required parameters: account id, warehouse, database, user, password, schema" - }, + data={"message": "Missing required parameters: passphrase, private key"}, ) try: - result = get_snowflake_schemas(account_id, database, warehouse, user, password, schema, role) + result = get_snowflake_schemas( + account_id=account_id, + database=database, + warehouse=warehouse, + user=auth_type_username, + password=auth_type_password, + schema=schema, + role=role, + passphrase=auth_type_passphrase, + private_key=auth_type_private_key, + auth_type=auth_type, + ) if len(result.keys()) == 0: return Response( status=status.HTTP_400_BAD_REQUEST, diff --git a/posthog/warehouse/models/external_data_schema.py b/posthog/warehouse/models/external_data_schema.py index b8219a6628c02..3b081d54f8501 100644 --- a/posthog/warehouse/models/external_data_schema.py +++ b/posthog/warehouse/models/external_data_schema.py @@ -1,5 +1,7 @@ from collections import defaultdict from datetime import datetime, timedelta +import tempfile +import os from typing import Optional from django.db import models from django_deprecate_fields import deprecate_field @@ -193,16 +195,43 @@ def filter_snowflake_incremental_fields(columns: list[tuple[str, str]]) -> list[ def get_snowflake_schemas( - account_id: str, database: str, warehouse: str, user: str, password: str, schema: str, role: Optional[str] = None + account_id: str, + database: str, + warehouse: str, + user: Optional[str], + password: Optional[str], + passphrase: Optional[str], + private_key: Optional[str], + auth_type: str, + schema: str, + role: Optional[str] = None, ) -> dict[str, list[tuple[str, str]]]: + auth_connect_args: dict[str, str | None] = {} + file_name: str | None = None + + if auth_type == "keypair" and private_key is not None: + with tempfile.NamedTemporaryFile(delete=False) as tf: + tf.write(private_key.encode("utf-8")) + file_name = tf.name + + auth_connect_args = { + "user": user, + "private_key_file": file_name, + "private_key_file_pwd": passphrase, + } + else: + auth_connect_args = { + "password": password, + "user": user, + } + with snowflake.connector.connect( - user=user, - password=password, account=account_id, warehouse=warehouse, database=database, schema="information_schema", role=role, + **auth_connect_args, ) as connection: with connection.cursor() as cursor: if cursor is None: @@ -218,7 +247,10 @@ def get_snowflake_schemas( for row in result: schema_list[row[0]].append((row[1], row[2])) - return schema_list + if file_name is not None: + os.unlink(file_name) + + return schema_list def filter_postgres_incremental_fields(columns: list[tuple[str, str]]) -> list[tuple[str, IncrementalFieldType]]: From 218f7ea980b5e53f4e5aeb0f49bb1e158a9700d0 Mon Sep 17 00:00:00 2001 From: Tom Owers Date: Wed, 4 Dec 2024 18:54:19 +0000 Subject: [PATCH 2/3] Fixed one missing func call --- mypy-baseline.txt | 238 +++++++++--------- posthog/warehouse/api/external_data_schema.py | 13 +- 2 files changed, 130 insertions(+), 121 deletions(-) diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 96984826e9c5a..3c6e549aa9663 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -1,67 +1,4 @@ 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_v2/schema_types.py:0: error: Statement is unreachable [unreachable] -posthog/temporal/data_imports/pipelines/sql_database_v2/schema_types.py:0: error: Non-overlapping equality check (left operand type: "Literal['text', 'double', 'bool', 'timestamp', 'bigint', 'json', 'decimal', 'wei', 'date', 'time'] | None", right operand type: "Literal['interval']") [comparison-overlap] -posthog/temporal/data_imports/pipelines/sql_database_v2/arrow_helpers.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/sql_database_v2/arrow_helpers.py:0: error: Invalid index type "str | None" for "dict[str, ndarray[Any, dtype[Any]]]"; expected type "str" [index] -posthog/temporal/data_imports/pipelines/sql_database_v2/arrow_helpers.py:0: error: Invalid index type "str | None" for "dict[str, ndarray[Any, dtype[Any]]]"; expected type "str" [index] -posthog/temporal/data_imports/pipelines/sql_database_v2/arrow_helpers.py:0: error: Invalid index type "str | None" for "dict[str, TColumnSchema]"; expected type "str" [index] -posthog/temporal/data_imports/pipelines/sql_database/helpers.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Item "None" of "Incremental[Any] | None" has no attribute "row_order" [union-attr] -posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Incompatible types in assignment (expression has type "Literal['asc', 'desc'] | Any | None", variable has type "Literal['asc', 'desc']") [assignment] -posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Column[Any]") [assignment] -posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Literal['asc', 'desc']") [assignment] -posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Item "None" of "dict[str, Any] | None" has no attribute "get" [union-attr] -posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Argument "primary_key" to "make_hints" has incompatible type "list[str] | None"; expected "str | Sequence[str] | Callable[[Any], str | Sequence[str]]" [arg-type] -posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/sql_database_v2/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] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "AuthConfigBase") [assignment] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Argument 1 to "get_auth_class" has incompatible type "Literal['bearer', 'api_key', 'http_basic'] | None"; expected "Literal['bearer', 'api_key', 'http_basic']" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Need type annotation for "dependency_graph" [var-annotated] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Incompatible types in assignment (expression has type "None", target has type "ResolvedParam") [assignment] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Incompatible return value type (got "tuple[TopologicalSorter[Any], dict[str, EndpointResource], dict[str, ResolvedParam]]", expected "tuple[Any, dict[str, EndpointResource], dict[str, ResolvedParam | None]]") [return-value] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Unsupported right operand type for in ("str | Endpoint | None") [operator] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Value of type variable "StrOrLiteralStr" of "parse" of "Formatter" cannot be "str | None" [type-var] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Unsupported right operand type for in ("dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None") [operator] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Unsupported right operand type for in ("dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None") [operator] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Value of type "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None" is not indexable [index] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Item "None" of "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None" has no attribute "pop" [union-attr] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Value of type "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None" is not indexable [index] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Item "None" of "str | None" has no attribute "format" [union-attr] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Argument 1 to "single_entity_path" has incompatible type "str | None"; expected "str" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Item "None" of "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None" has no attribute "items" [union-attr] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Incompatible types in assignment (expression has type "str | None", variable has type "str") [assignment] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Incompatible types in assignment (expression has type "str | None", variable has type "str") [assignment] -posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Statement is unreachable [unreachable] -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, Any]" [dict-item] -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/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] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 3 to "source" has incompatible type "str | None"; expected "str" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 4 to "source" has incompatible type "int | None"; expected "int" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 6 to "source" has incompatible type "Schema | None"; expected "Schema" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 7 to "source" has incompatible type "Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict | None"; expected "Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 8 to "source" has incompatible type "type[BaseConfiguration] | None"; expected "type[BaseConfiguration]" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 1 to "build_resource_dependency_graph" has incompatible type "EndpointResourceBase | None"; expected "EndpointResourceBase" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Incompatible types in assignment (expression has type "list[str] | None", variable has type "list[str]") [assignment] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 1 to "setup_incremental_object" has incompatible type "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None"; expected "dict[str, Any]" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument "base_url" to "RESTClient" has incompatible type "str | None"; expected "str" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 1 to "exclude_keys" has incompatible type "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None"; expected "Mapping[str, Any]" [arg-type] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Incompatible default for argument "resolved_param" (default has type "ResolvedParam | None", argument has type "ResolvedParam") [assignment] -posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] 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] @@ -436,40 +373,9 @@ posthog/test/test_feature_flag_analytics.py:0: error: Item "None" of "Dashboard 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/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/pipelines/zendesk/__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/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/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/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: error: No overload variant of "with_only_columns" of "Select" matches argument type "ReadOnlyColumnCollection[str, Column[Any]]" [call-overload] -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: Possible overload variants: -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], /) -> Select[tuple[_T0]] -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0, _T1] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], TypedColumnsClauseRole[_T1] | SQLCoreOperations[_T1] | type[_T1], /) -> Select[tuple[_T0, _T1]] -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0, _T1, _T2] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], TypedColumnsClauseRole[_T1] | SQLCoreOperations[_T1] | type[_T1], TypedColumnsClauseRole[_T2] | SQLCoreOperations[_T2] | type[_T2], /) -> Select[tuple[_T0, _T1, _T2]] -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0, _T1, _T2, _T3] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], TypedColumnsClauseRole[_T1] | SQLCoreOperations[_T1] | type[_T1], TypedColumnsClauseRole[_T2] | SQLCoreOperations[_T2] | type[_T2], TypedColumnsClauseRole[_T3] | SQLCoreOperations[_T3] | type[_T3], /) -> Select[tuple[_T0, _T1, _T2, _T3]] -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0, _T1, _T2, _T3, _T4] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], TypedColumnsClauseRole[_T1] | SQLCoreOperations[_T1] | type[_T1], TypedColumnsClauseRole[_T2] | SQLCoreOperations[_T2] | type[_T2], TypedColumnsClauseRole[_T3] | SQLCoreOperations[_T3] | type[_T3], TypedColumnsClauseRole[_T4] | SQLCoreOperations[_T4] | type[_T4], /) -> Select[tuple[_T0, _T1, _T2, _T3, _T4]] -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0, _T1, _T2, _T3, _T4, _T5] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], TypedColumnsClauseRole[_T1] | SQLCoreOperations[_T1] | type[_T1], TypedColumnsClauseRole[_T2] | SQLCoreOperations[_T2] | type[_T2], TypedColumnsClauseRole[_T3] | SQLCoreOperations[_T3] | type[_T3], TypedColumnsClauseRole[_T4] | SQLCoreOperations[_T4] | type[_T4], TypedColumnsClauseRole[_T5] | SQLCoreOperations[_T5] | type[_T5], /) -> Select[tuple[_T0, _T1, _T2, _T3, _T4, _T5]] -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0, _T1, _T2, _T3, _T4, _T5, _T6] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], TypedColumnsClauseRole[_T1] | SQLCoreOperations[_T1] | type[_T1], TypedColumnsClauseRole[_T2] | SQLCoreOperations[_T2] | type[_T2], TypedColumnsClauseRole[_T3] | SQLCoreOperations[_T3] | type[_T3], TypedColumnsClauseRole[_T4] | SQLCoreOperations[_T4] | type[_T4], TypedColumnsClauseRole[_T5] | SQLCoreOperations[_T5] | type[_T5], TypedColumnsClauseRole[_T6] | SQLCoreOperations[_T6] | type[_T6], /) -> Select[tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]] -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], TypedColumnsClauseRole[_T1] | SQLCoreOperations[_T1] | type[_T1], TypedColumnsClauseRole[_T2] | SQLCoreOperations[_T2] | type[_T2], TypedColumnsClauseRole[_T3] | SQLCoreOperations[_T3] | type[_T3], TypedColumnsClauseRole[_T4] | SQLCoreOperations[_T4] | type[_T4], TypedColumnsClauseRole[_T5] | SQLCoreOperations[_T5] | type[_T5], TypedColumnsClauseRole[_T6] | SQLCoreOperations[_T6] | type[_T6], TypedColumnsClauseRole[_T7] | SQLCoreOperations[_T7] | type[_T7], /) -> Select[tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7]] -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def with_only_columns(self, *entities: TypedColumnsClauseRole[Any] | ColumnsClauseRole | SQLCoreOperations[Any] | Literal['*', 1] | type[Any] | Inspectable[_HasClauseElement[Any]] | _HasClauseElement[Any], maintain_column_froms: bool = ..., **Any) -> Select[Any] -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: error: No overload variant of "resource" matches argument types "Callable[[Engine, Table, int, Literal['sqlalchemy', 'pyarrow', 'pandas', 'connectorx'], Incremental[Any] | None, bool, Callable[[Table], None] | None, Literal['minimal', 'full', 'full_with_precision'], dict[str, Any] | None, Callable[[TypeEngine[Any]], TypeEngine[Any] | type[TypeEngine[Any]] | None] | None, list[str] | None, Callable[[Select[Any], Table], Select[Any]] | None, list[str] | None], Iterator[Any]]", "str", "list[str] | None", "list[str] | None", "dict[str, TColumnSchema]", "Collection[str]", "str" [call-overload] -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: Possible overload variants: -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [TResourceFunParams`-1, TDltResourceImpl: DltResource] resource(Callable[TResourceFunParams, Any], /, name: str = ..., table_name: str | Callable[[Any], str] = ..., max_table_nesting: int = ..., write_disposition: Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict | Callable[[Any], Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict] = ..., columns: dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel] | Callable[[Any], dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel]] = ..., primary_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., merge_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., schema_contract: Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict | Callable[[Any], Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict] = ..., table_format: Literal['iceberg', 'delta', 'hive'] | Callable[[Any], Literal['iceberg', 'delta', 'hive']] = ..., file_format: Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference'] | Callable[[Any], Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference']] = ..., references: Sequence[TTableReference] | Callable[[Any], Sequence[TTableReference]] = ..., selected: bool = ..., spec: type[BaseConfiguration] = ..., parallelized: bool = ..., _impl_cls: type[TDltResourceImpl] = ...) -> TDltResourceImpl -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [TDltResourceImpl: DltResource] resource(None = ..., /, name: str = ..., table_name: str | Callable[[Any], str] = ..., max_table_nesting: int = ..., write_disposition: Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict | Callable[[Any], Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict] = ..., columns: dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel] | Callable[[Any], dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel]] = ..., primary_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., merge_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., schema_contract: Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict | Callable[[Any], Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict] = ..., table_format: Literal['iceberg', 'delta', 'hive'] | Callable[[Any], Literal['iceberg', 'delta', 'hive']] = ..., file_format: Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference'] | Callable[[Any], Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference']] = ..., references: Sequence[TTableReference] | Callable[[Any], Sequence[TTableReference]] = ..., selected: bool = ..., spec: type[BaseConfiguration] = ..., parallelized: bool = ..., _impl_cls: type[TDltResourceImpl] = ...) -> Callable[[Callable[TResourceFunParams, Any]], TDltResourceImpl] -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [TDltResourceImpl: DltResource] resource(None = ..., /, name: str | Callable[[Any], str] = ..., table_name: str | Callable[[Any], str] = ..., max_table_nesting: int = ..., write_disposition: Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict | Callable[[Any], Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict] = ..., columns: dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel] | Callable[[Any], dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel]] = ..., primary_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., merge_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., schema_contract: Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict | Callable[[Any], Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict] = ..., table_format: Literal['iceberg', 'delta', 'hive'] | Callable[[Any], Literal['iceberg', 'delta', 'hive']] = ..., file_format: Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference'] | Callable[[Any], Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference']] = ..., references: Sequence[TTableReference] | Callable[[Any], Sequence[TTableReference]] = ..., selected: bool = ..., spec: type[BaseConfiguration] = ..., parallelized: bool = ..., _impl_cls: type[TDltResourceImpl] = ..., standalone: Literal[True] = ...) -> Callable[[Callable[TResourceFunParams, Any]], Callable[TResourceFunParams, TDltResourceImpl]] -posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [TDltResourceImpl: DltResource] resource(list[Any] | tuple[Any] | Iterator[Any], /, name: str = ..., table_name: str | Callable[[Any], str] = ..., max_table_nesting: int = ..., write_disposition: Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict | Callable[[Any], Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict] = ..., columns: dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel] | Callable[[Any], dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel]] = ..., primary_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., merge_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., schema_contract: Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict | Callable[[Any], Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict] = ..., table_format: Literal['iceberg', 'delta', 'hive'] | Callable[[Any], Literal['iceberg', 'delta', 'hive']] = ..., file_format: Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference'] | Callable[[Any], Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference']] = ..., references: Sequence[TTableReference] | Callable[[Any], Sequence[TTableReference]] = ..., selected: bool = ..., spec: type[BaseConfiguration] = ..., parallelized: bool = ..., _impl_cls: type[TDltResourceImpl] = ...) -> TDltResourceImpl +posthog/temporal/data_imports/pipelines/sql_database_v2/schema_types.py:0: error: Statement is unreachable [unreachable] +posthog/temporal/data_imports/pipelines/sql_database_v2/schema_types.py:0: error: Non-overlapping equality check (left operand type: "Literal['text', 'double', 'bool', 'timestamp', 'bigint', 'json', 'decimal', 'wei', 'date', 'time'] | None", right operand type: "Literal['interval']") [comparison-overlap] +posthog/temporal/data_imports/pipelines/sql_database/helpers.py:0: error: Unused "type: ignore" comment [unused-ignore] 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: @@ -603,22 +509,10 @@ posthog/warehouse/data_load/validate_schema.py:0: error: Incompatible types in a 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/warehouse/data_load/source_templates.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "Type") [assignment] -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/table.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/warehouse/api/table.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/warehouse/api/table.py:0: error: Unused "type: ignore" comment [unused-ignore] -posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "tuple[()]" [call-overload] -posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py:0: note: Possible overload variants: -posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py:0: note: def get(self, Type, /) -> Sequence[str] | None -posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py:0: note: def get(self, Type, Sequence[str], /) -> Sequence[str] -posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py:0: note: def [_T] get(self, Type, _T, /) -> Sequence[str] | _T -posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py:0: error: Argument "source_id" to "sync_old_schemas_with_new_schemas" has incompatible type "str"; expected "UUID" [arg-type] +posthog/temporal/data_imports/pipelines/sql_database_v2/arrow_helpers.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/sql_database_v2/arrow_helpers.py:0: error: Invalid index type "str | None" for "dict[str, ndarray[Any, dtype[Any]]]"; expected type "str" [index] +posthog/temporal/data_imports/pipelines/sql_database_v2/arrow_helpers.py:0: error: Invalid index type "str | None" for "dict[str, ndarray[Any, dtype[Any]]]"; expected type "str" [index] +posthog/temporal/data_imports/pipelines/sql_database_v2/arrow_helpers.py:0: error: Invalid index type "str | None" for "dict[str, TColumnSchema]"; expected type "str" [index] posthog/tasks/exports/test/test_csv_exporter.py:0: error: Function is missing a return type annotation [no-untyped-def] posthog/tasks/exports/test/test_csv_exporter.py:0: error: Function is missing a type annotation [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] @@ -792,6 +686,22 @@ posthog/temporal/tests/batch_exports/test_batch_exports.py:0: error: TypedDict k posthog/temporal/data_modeling/run_workflow.py:0: error: Dict entry 20 has incompatible type "str": "Literal['complex']"; expected "str": "Literal['text', 'double', 'bool', 'timestamp', 'bigint', 'binary', 'json', 'decimal', 'wei', 'date', 'time']" [dict-item] posthog/temporal/data_modeling/run_workflow.py:0: error: Dict entry 21 has incompatible type "str": "Literal['complex']"; expected "str": "Literal['text', 'double', 'bool', 'timestamp', 'bigint', 'binary', 'json', 'decimal', 'wei', 'date', 'time']" [dict-item] posthog/temporal/data_modeling/run_workflow.py:0: error: Dict entry 22 has incompatible type "str": "Literal['complex']"; expected "str": "Literal['text', 'double', 'bool', 'timestamp', 'bigint', 'binary', 'json', 'decimal', 'wei', 'date', 'time']" [dict-item] +posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "tuple[()]" [call-overload] +posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py:0: note: Possible overload variants: +posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py:0: note: def get(self, Type, /) -> Sequence[str] | None +posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py:0: note: def get(self, Type, Sequence[str], /) -> Sequence[str] +posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py:0: note: def [_T] get(self, Type, _T, /) -> Sequence[str] | _T +posthog/temporal/data_imports/workflow_activities/sync_new_schemas.py:0: error: Argument "source_id" to "sync_old_schemas_with_new_schemas" has incompatible type "str"; expected "UUID" [arg-type] +posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Item "None" of "Incremental[Any] | None" has no attribute "row_order" [union-attr] +posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Incompatible types in assignment (expression has type "Literal['asc', 'desc'] | Any | None", variable has type "Literal['asc', 'desc']") [assignment] +posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Column[Any]") [assignment] +posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Literal['asc', 'desc']") [assignment] +posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Item "None" of "dict[str, Any] | None" has no attribute "get" [union-attr] +posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Argument "primary_key" to "make_hints" has incompatible type "list[str] | None"; expected "str | Sequence[str] | Callable[[Any], str | Sequence[str]]" [arg-type] +posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/sql_database_v2/helpers.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/temporal/data_imports/pipelines/pipeline_sync.py:0: error: "FilesystemDestinationClientConfiguration" has no attribute "delta_jobs_per_write" [attr-defined] posthog/temporal/data_imports/pipelines/pipeline_sync.py:0: error: "type[FilesystemDestinationClientConfiguration]" has no attribute "delta_jobs_per_write" [attr-defined] posthog/temporal/data_imports/pipelines/pipeline_sync.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "DataWarehouseCredential | Combinable | None") [assignment] @@ -824,6 +734,23 @@ 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: Need type annotation for "_execute_async_calls" (hint: "_execute_async_calls: list[] = ...") [var-annotated] posthog/temporal/tests/batch_exports/test_snowflake_batch_export_workflow.py:0: error: Need type annotation for "_cursors" (hint: "_cursors: list[] = ...") [var-annotated] 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/data_imports/pipelines/sql_database_v2/__init__.py:0: error: No overload variant of "with_only_columns" of "Select" matches argument type "ReadOnlyColumnCollection[str, Column[Any]]" [call-overload] +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: Possible overload variants: +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], /) -> Select[tuple[_T0]] +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0, _T1] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], TypedColumnsClauseRole[_T1] | SQLCoreOperations[_T1] | type[_T1], /) -> Select[tuple[_T0, _T1]] +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0, _T1, _T2] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], TypedColumnsClauseRole[_T1] | SQLCoreOperations[_T1] | type[_T1], TypedColumnsClauseRole[_T2] | SQLCoreOperations[_T2] | type[_T2], /) -> Select[tuple[_T0, _T1, _T2]] +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0, _T1, _T2, _T3] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], TypedColumnsClauseRole[_T1] | SQLCoreOperations[_T1] | type[_T1], TypedColumnsClauseRole[_T2] | SQLCoreOperations[_T2] | type[_T2], TypedColumnsClauseRole[_T3] | SQLCoreOperations[_T3] | type[_T3], /) -> Select[tuple[_T0, _T1, _T2, _T3]] +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0, _T1, _T2, _T3, _T4] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], TypedColumnsClauseRole[_T1] | SQLCoreOperations[_T1] | type[_T1], TypedColumnsClauseRole[_T2] | SQLCoreOperations[_T2] | type[_T2], TypedColumnsClauseRole[_T3] | SQLCoreOperations[_T3] | type[_T3], TypedColumnsClauseRole[_T4] | SQLCoreOperations[_T4] | type[_T4], /) -> Select[tuple[_T0, _T1, _T2, _T3, _T4]] +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0, _T1, _T2, _T3, _T4, _T5] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], TypedColumnsClauseRole[_T1] | SQLCoreOperations[_T1] | type[_T1], TypedColumnsClauseRole[_T2] | SQLCoreOperations[_T2] | type[_T2], TypedColumnsClauseRole[_T3] | SQLCoreOperations[_T3] | type[_T3], TypedColumnsClauseRole[_T4] | SQLCoreOperations[_T4] | type[_T4], TypedColumnsClauseRole[_T5] | SQLCoreOperations[_T5] | type[_T5], /) -> Select[tuple[_T0, _T1, _T2, _T3, _T4, _T5]] +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0, _T1, _T2, _T3, _T4, _T5, _T6] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], TypedColumnsClauseRole[_T1] | SQLCoreOperations[_T1] | type[_T1], TypedColumnsClauseRole[_T2] | SQLCoreOperations[_T2] | type[_T2], TypedColumnsClauseRole[_T3] | SQLCoreOperations[_T3] | type[_T3], TypedColumnsClauseRole[_T4] | SQLCoreOperations[_T4] | type[_T4], TypedColumnsClauseRole[_T5] | SQLCoreOperations[_T5] | type[_T5], TypedColumnsClauseRole[_T6] | SQLCoreOperations[_T6] | type[_T6], /) -> Select[tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]] +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7] with_only_columns(self, TypedColumnsClauseRole[_T0] | SQLCoreOperations[_T0] | type[_T0], TypedColumnsClauseRole[_T1] | SQLCoreOperations[_T1] | type[_T1], TypedColumnsClauseRole[_T2] | SQLCoreOperations[_T2] | type[_T2], TypedColumnsClauseRole[_T3] | SQLCoreOperations[_T3] | type[_T3], TypedColumnsClauseRole[_T4] | SQLCoreOperations[_T4] | type[_T4], TypedColumnsClauseRole[_T5] | SQLCoreOperations[_T5] | type[_T5], TypedColumnsClauseRole[_T6] | SQLCoreOperations[_T6] | type[_T6], TypedColumnsClauseRole[_T7] | SQLCoreOperations[_T7] | type[_T7], /) -> Select[tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7]] +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def with_only_columns(self, *entities: TypedColumnsClauseRole[Any] | ColumnsClauseRole | SQLCoreOperations[Any] | Literal['*', 1] | type[Any] | Inspectable[_HasClauseElement[Any]] | _HasClauseElement[Any], maintain_column_froms: bool = ..., **Any) -> Select[Any] +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: error: No overload variant of "resource" matches argument types "Callable[[Engine, Table, int, Literal['sqlalchemy', 'pyarrow', 'pandas', 'connectorx'], Incremental[Any] | None, bool, Callable[[Table], None] | None, Literal['minimal', 'full', 'full_with_precision'], dict[str, Any] | None, Callable[[TypeEngine[Any]], TypeEngine[Any] | type[TypeEngine[Any]] | None] | None, list[str] | None, Callable[[Select[Any], Table], Select[Any]] | None, list[str] | None], Iterator[Any]]", "str", "list[str] | None", "list[str] | None", "dict[str, TColumnSchema]", "Collection[str]", "str" [call-overload] +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: Possible overload variants: +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [TResourceFunParams`-1, TDltResourceImpl: DltResource] resource(Callable[TResourceFunParams, Any], /, name: str = ..., table_name: str | Callable[[Any], str] = ..., max_table_nesting: int = ..., write_disposition: Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict | Callable[[Any], Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict] = ..., columns: dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel] | Callable[[Any], dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel]] = ..., primary_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., merge_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., schema_contract: Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict | Callable[[Any], Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict] = ..., table_format: Literal['iceberg', 'delta', 'hive'] | Callable[[Any], Literal['iceberg', 'delta', 'hive']] = ..., file_format: Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference'] | Callable[[Any], Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference']] = ..., references: Sequence[TTableReference] | Callable[[Any], Sequence[TTableReference]] = ..., selected: bool = ..., spec: type[BaseConfiguration] = ..., parallelized: bool = ..., _impl_cls: type[TDltResourceImpl] = ...) -> TDltResourceImpl +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [TDltResourceImpl: DltResource] resource(None = ..., /, name: str = ..., table_name: str | Callable[[Any], str] = ..., max_table_nesting: int = ..., write_disposition: Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict | Callable[[Any], Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict] = ..., columns: dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel] | Callable[[Any], dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel]] = ..., primary_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., merge_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., schema_contract: Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict | Callable[[Any], Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict] = ..., table_format: Literal['iceberg', 'delta', 'hive'] | Callable[[Any], Literal['iceberg', 'delta', 'hive']] = ..., file_format: Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference'] | Callable[[Any], Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference']] = ..., references: Sequence[TTableReference] | Callable[[Any], Sequence[TTableReference]] = ..., selected: bool = ..., spec: type[BaseConfiguration] = ..., parallelized: bool = ..., _impl_cls: type[TDltResourceImpl] = ...) -> Callable[[Callable[TResourceFunParams, Any]], TDltResourceImpl] +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [TDltResourceImpl: DltResource] resource(None = ..., /, name: str | Callable[[Any], str] = ..., table_name: str | Callable[[Any], str] = ..., max_table_nesting: int = ..., write_disposition: Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict | Callable[[Any], Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict] = ..., columns: dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel] | Callable[[Any], dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel]] = ..., primary_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., merge_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., schema_contract: Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict | Callable[[Any], Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict] = ..., table_format: Literal['iceberg', 'delta', 'hive'] | Callable[[Any], Literal['iceberg', 'delta', 'hive']] = ..., file_format: Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference'] | Callable[[Any], Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference']] = ..., references: Sequence[TTableReference] | Callable[[Any], Sequence[TTableReference]] = ..., selected: bool = ..., spec: type[BaseConfiguration] = ..., parallelized: bool = ..., _impl_cls: type[TDltResourceImpl] = ..., standalone: Literal[True] = ...) -> Callable[[Callable[TResourceFunParams, Any]], Callable[TResourceFunParams, TDltResourceImpl]] +posthog/temporal/data_imports/pipelines/sql_database_v2/__init__.py:0: note: def [TDltResourceImpl: DltResource] resource(list[Any] | tuple[Any] | Iterator[Any], /, name: str = ..., table_name: str | Callable[[Any], str] = ..., max_table_nesting: int = ..., write_disposition: Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict | Callable[[Any], Literal['skip', 'append', 'replace', 'merge'] | TWriteDispositionDict | TMergeDispositionDict | TScd2StrategyDict] = ..., columns: dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel] | Callable[[Any], dict[str, TColumnSchema] | Sequence[TColumnSchema] | BaseModel | type[BaseModel]] = ..., primary_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., merge_key: str | Sequence[str] | Callable[[Any], str | Sequence[str]] = ..., schema_contract: Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict | Callable[[Any], Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict] = ..., table_format: Literal['iceberg', 'delta', 'hive'] | Callable[[Any], Literal['iceberg', 'delta', 'hive']] = ..., file_format: Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference'] | Callable[[Any], Literal['preferred', 'jsonl', 'typed-jsonl', 'insert_values', 'parquet', 'csv', 'reference']] = ..., references: Sequence[TTableReference] | Callable[[Any], Sequence[TTableReference]] = ..., selected: bool = ..., spec: type[BaseConfiguration] = ..., parallelized: bool = ..., _impl_cls: type[TDltResourceImpl] = ...) -> TDltResourceImpl 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] @@ -831,22 +758,79 @@ posthog/api/plugin_log_entry.py:0: error: Module "django.utils.timezone" does no posthog/api/plugin_log_entry.py:0: error: Name "timezone.datetime" is not defined [name-defined] posthog/api/plugin_log_entry.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] 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/temporal/data_imports/external_data_job.py:0: error: Argument "status" to "update_external_job_status" has incompatible type "str"; expected "Status" [arg-type] posthog/api/sharing.py:0: error: Item "None" of "list[Any] | None" has no attribute "__iter__" (not iterable) [union-attr] +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] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "AuthConfigBase") [assignment] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Argument 1 to "get_auth_class" has incompatible type "Literal['bearer', 'api_key', 'http_basic'] | None"; expected "Literal['bearer', 'api_key', 'http_basic']" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Need type annotation for "dependency_graph" [var-annotated] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Incompatible types in assignment (expression has type "None", target has type "ResolvedParam") [assignment] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Incompatible return value type (got "tuple[TopologicalSorter[Any], dict[str, EndpointResource], dict[str, ResolvedParam]]", expected "tuple[Any, dict[str, EndpointResource], dict[str, ResolvedParam | None]]") [return-value] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Unsupported right operand type for in ("str | Endpoint | None") [operator] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Value of type variable "StrOrLiteralStr" of "parse" of "Formatter" cannot be "str | None" [type-var] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Unsupported right operand type for in ("dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None") [operator] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Unsupported right operand type for in ("dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None") [operator] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Value of type "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None" is not indexable [index] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Item "None" of "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None" has no attribute "pop" [union-attr] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Value of type "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None" is not indexable [index] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Item "None" of "str | None" has no attribute "format" [union-attr] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Argument 1 to "single_entity_path" has incompatible type "str | None"; expected "str" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Item "None" of "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None" has no attribute "items" [union-attr] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Incompatible types in assignment (expression has type "str | None", variable has type "str") [assignment] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Incompatible types in assignment (expression has type "str | None", variable has type "str") [assignment] +posthog/temporal/data_imports/pipelines/rest_source/config_setup.py:0: error: Statement is unreachable [unreachable] +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, Any]" [dict-item] +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/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/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/data_imports/test_end_to_end.py:0: error: Unused "type: ignore" comment [unused-ignore] +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] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 3 to "source" has incompatible type "str | None"; expected "str" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 4 to "source" has incompatible type "int | None"; expected "int" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 6 to "source" has incompatible type "Schema | None"; expected "Schema" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 7 to "source" has incompatible type "Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict | None"; expected "Literal['evolve', 'discard_value', 'freeze', 'discard_row'] | TSchemaContractDict" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 8 to "source" has incompatible type "type[BaseConfiguration] | None"; expected "type[BaseConfiguration]" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 1 to "build_resource_dependency_graph" has incompatible type "EndpointResourceBase | None"; expected "EndpointResourceBase" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Incompatible types in assignment (expression has type "list[str] | None", variable has type "list[str]") [assignment] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 1 to "setup_incremental_object" has incompatible type "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None"; expected "dict[str, Any]" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument "base_url" to "RESTClient" has incompatible type "str | None"; expected "str" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Argument 1 to "exclude_keys" has incompatible type "dict[str, ResolveParamConfig | IncrementalParamConfig | Any] | None"; expected "Mapping[str, Any]" [arg-type] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Incompatible default for argument "resolved_param" (default has type "ResolvedParam | None", argument has type "ResolvedParam") [assignment] +posthog/temporal/data_imports/pipelines/rest_source/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/api/test/test_team.py:0: error: "HttpResponse" has no attribute "json" [attr-defined] posthog/api/test/test_team.py:0: error: "HttpResponse" has no attribute "json" [attr-defined] posthog/test/test_middleware.py:0: error: Incompatible types in assignment (expression has type "_MonkeyPatchedWSGIResponse", variable has type "_MonkeyPatchedResponse") [assignment] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/zendesk/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__init__.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/pipelines/vitally/__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/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/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/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] posthog/management/commands/test/test_create_batch_export_from_app.py:0: error: Unpacked dict entry 1 has incompatible type "str"; expected "SupportsKeysAndGetItem[str, str]" [dict-item] @@ -888,6 +872,22 @@ posthog/api/test/batch_exports/test_update.py:0: error: Value of type "BatchExpo 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_pause.py:0: error: "batch_export_delete_schedule" does not return a value (it only ever returns None) [func-returns-value] +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/table.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/warehouse/api/table.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/warehouse/api/table.py:0: error: Unused "type: ignore" comment [unused-ignore] +posthog/temporal/data_imports/external_data_job.py:0: error: Argument "status" to "update_external_job_status" has incompatible type "str"; expected "Status" [arg-type] +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/data_imports/test_end_to_end.py:0: error: Unused "type: ignore" comment [unused-ignore] posthog/api/query.py:0: error: Statement is unreachable [unreachable] 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] diff --git a/posthog/warehouse/api/external_data_schema.py b/posthog/warehouse/api/external_data_schema.py index 55a4447907021..9391268bb69d0 100644 --- a/posthog/warehouse/api/external_data_schema.py +++ b/posthog/warehouse/api/external_data_schema.py @@ -350,14 +350,23 @@ def incremental_fields(self, request: Request, *args: Any, **kwargs: Any): sf_schema = source.job_inputs.get("schema") role = source.job_inputs.get("role") + auth_type = source.job_inputs.get("auth_type", "password") + auth_type_username = source.job_inputs.get("user") + auth_type_password = source.job_inputs.get("password") + auth_type_passphrase = source.job_inputs.get("passphrase") + auth_type_private_key = source.job_inputs.get("private_key") + sf_schemas = get_snowflake_schemas( account_id=account_id, database=database, warehouse=warehouse, - user=user, - password=password, + user=auth_type_username, + password=auth_type_password, schema=sf_schema, role=role, + auth_type=auth_type, + passphrase=auth_type_passphrase, + private_key=auth_type_private_key, ) columns = sf_schemas.get(instance.name, []) From f3d0f6ff22424da532d4bd9a73a3e674cfe23f62 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 6 Dec 2024 12:52:48 +0000 Subject: [PATCH 3/3] Update UI snapshots for `chromium` (2) --- ...details--data-table-events-query--dark.png | Bin 9133 -> 9758 bytes ...etails--data-table-events-query--light.png | Bin 8870 -> 9348 bytes ...details--data-table-hog-ql-query--dark.png | Bin 9133 -> 9758 bytes ...etails--data-table-hog-ql-query--light.png | Bin 8870 -> 9348 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/frontend/__snapshots__/components-cards-insight-details--data-table-events-query--dark.png b/frontend/__snapshots__/components-cards-insight-details--data-table-events-query--dark.png index 1f129b49b9cf822dce63da388fb5d77c06eca30a..24cc8f4b2f6b609f44ea44f8558fbb13858c9e81 100644 GIT binary patch literal 9758 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 literal 9133 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 diff --git a/frontend/__snapshots__/components-cards-insight-details--data-table-events-query--light.png b/frontend/__snapshots__/components-cards-insight-details--data-table-events-query--light.png index 3077ca6a3636895db6b9f7de5a40a87e34d24910..64fd850a0fc2515ba4078af1164ca79a87e668e9 100644 GIT binary patch literal 9348 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 TY|7wkMTlol6r}Qy2JikCz>6_T literal 8870 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 F{0HhSB_RL+ diff --git a/frontend/__snapshots__/components-cards-insight-details--data-table-hog-ql-query--dark.png b/frontend/__snapshots__/components-cards-insight-details--data-table-hog-ql-query--dark.png index 1f129b49b9cf822dce63da388fb5d77c06eca30a..24cc8f4b2f6b609f44ea44f8558fbb13858c9e81 100644 GIT binary patch literal 9758 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 literal 9133 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 diff --git a/frontend/__snapshots__/components-cards-insight-details--data-table-hog-ql-query--light.png b/frontend/__snapshots__/components-cards-insight-details--data-table-hog-ql-query--light.png index 3077ca6a3636895db6b9f7de5a40a87e34d24910..64fd850a0fc2515ba4078af1164ca79a87e668e9 100644 GIT binary patch literal 9348 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 TY|7wkMTlol6r}Qy2JikCz>6_T literal 8870 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 F{0HhSB_RL+