diff --git a/package.json b/package.json index be3be7cd6ae02..d57d8824da145 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "build:esbuild": "node frontend/build.mjs", "schema:build": "pnpm run schema:build:json && pnpm run schema:build:python", "schema:build:json": "ts-json-schema-generator -f tsconfig.json --path 'frontend/src/*.ts' --type 'QuerySchema' --no-type-check > frontend/src/queries/schema.json && prettier --write frontend/src/queries/schema.json", - "schema:build:python": "datamodel-codegen --collapse-root-models --disable-timestamp --use-one-literal-as-default --use-default-kwarg --use-subclass-enum --input frontend/src/queries/schema.json --input-file-type jsonschema --output posthog/schema.py --output-model-type pydantic_v2.BaseModel && black posthog/schema.py", + "schema:build:python": "datamodel-codegen --collapse-root-models --disable-timestamp --use-subclass-enum --input frontend/src/queries/schema.json --input-file-type jsonschema --output posthog/schema.py && black posthog/schema.py", "grammar:build": "cd posthog/hogql/grammar && antlr -Dlanguage=Python3 HogQLLexer.g4 && antlr -visitor -no-listener -Dlanguage=Python3 HogQLParser.g4", "packages:build": "pnpm packages:build:apps-common && pnpm packages:build:lemon-ui", "packages:build:apps-common": "cd frontend/@posthog/apps-common && pnpm i && pnpm build", diff --git a/playwright/e2e-vrt/layout/Navigation.spec.ts-snapshots/Navigation-App-Page-With-Side-Bar-Hidden-Mobile-1-chromium-linux.png b/playwright/e2e-vrt/layout/Navigation.spec.ts-snapshots/Navigation-App-Page-With-Side-Bar-Hidden-Mobile-1-chromium-linux.png index ab79c58ee2eaf..3b185216c6362 100644 Binary files a/playwright/e2e-vrt/layout/Navigation.spec.ts-snapshots/Navigation-App-Page-With-Side-Bar-Hidden-Mobile-1-chromium-linux.png and b/playwright/e2e-vrt/layout/Navigation.spec.ts-snapshots/Navigation-App-Page-With-Side-Bar-Hidden-Mobile-1-chromium-linux.png differ diff --git a/playwright/e2e-vrt/layout/Navigation.spec.ts-snapshots/Navigation-App-Page-With-Side-Bar-Shown-Mobile-1-chromium-linux.png b/playwright/e2e-vrt/layout/Navigation.spec.ts-snapshots/Navigation-App-Page-With-Side-Bar-Shown-Mobile-1-chromium-linux.png index 8b8203a70dcf5..13d70cdd05948 100644 Binary files a/playwright/e2e-vrt/layout/Navigation.spec.ts-snapshots/Navigation-App-Page-With-Side-Bar-Shown-Mobile-1-chromium-linux.png and b/playwright/e2e-vrt/layout/Navigation.spec.ts-snapshots/Navigation-App-Page-With-Side-Bar-Shown-Mobile-1-chromium-linux.png differ diff --git a/posthog/api/insight.py b/posthog/api/insight.py index 8fc0dfa282735..28713fd083f5e 100644 --- a/posthog/api/insight.py +++ b/posthog/api/insight.py @@ -138,7 +138,7 @@ def parse(self, stream, media_type=None, parser_context=None): try: query = data.get("query", None) if query: - schema.Model.model_validate(query) + schema.Model.parse_obj(query) except Exception as error: raise ParseError(detail=str(error)) else: diff --git a/posthog/api/query.py b/posthog/api/query.py index c3cbb48cc9529..385f14d2f7905 100644 --- a/posthog/api/query.py +++ b/posthog/api/query.py @@ -50,7 +50,7 @@ class QuerySchemaParser(JSONParser): @staticmethod def validate_query(data) -> Dict: try: - schema.Model.model_validate(data) + schema.Model.parse_obj(data) # currently we have to return data not the parsed Model # because pydantic doesn't know to discriminate on 'kind' # if we can get this correctly typed we can return the parsed model @@ -204,11 +204,11 @@ def process_query(team: Team, query_json: Dict, default_limit: Optional[int] = N tag_queries(query=query_json) if query_kind == "EventsQuery": - events_query = EventsQuery.model_validate(query_json) + events_query = EventsQuery.parse_obj(query_json) events_response = run_events_query(query=events_query, team=team, default_limit=default_limit) return _unwrap_pydantic_dict(events_response) elif query_kind == "HogQLQuery": - hogql_query = HogQLQuery.model_validate(query_json) + hogql_query = HogQLQuery.parse_obj(query_json) hogql_response = execute_hogql_query( query_type="HogQLQuery", query=hogql_query.query, @@ -218,7 +218,7 @@ def process_query(team: Team, query_json: Dict, default_limit: Optional[int] = N ) return _unwrap_pydantic_dict(hogql_response) elif query_kind == "HogQLMetadata": - metadata_query = HogQLMetadata.model_validate(query_json) + metadata_query = HogQLMetadata.parse_obj(query_json) metadata_response = get_hogql_metadata(query=metadata_query, team=team) return _unwrap_pydantic_dict(metadata_response) elif query_kind == "LifecycleQuery": diff --git a/posthog/api/test/test_query.py b/posthog/api/test/test_query.py index cde8de9c22196..4e046a9268059 100644 --- a/posthog/api/test/test_query.py +++ b/posthog/api/test/test_query.py @@ -407,7 +407,7 @@ def test_full_hogql_query(self): with freeze_time("2020-01-10 12:14:00"): query = HogQLQuery(query="select event, distinct_id, properties.key from events order by timestamp") api_response = self.client.post(f"/api/projects/{self.team.id}/query/", {"query": query.dict()}).json() - query.response = HogQLQueryResponse.model_validate(api_response) + query.response = HogQLQueryResponse.parse_obj(api_response) self.assertEqual(query.response.results and len(query.response.results), 4) self.assertEqual( @@ -475,7 +475,7 @@ def test_invalid_query_kind(self): assert api_response.status_code == 400 assert api_response.json()["code"] == "parse_error" assert "validation errors for Model" in api_response.json()["detail"] - assert "type=literal_error, input_value='Tomato Soup'" in api_response.json()["detail"] + assert "type=value_error.const; given=Tomato Soup" in api_response.json()["detail"] @snapshot_clickhouse_queries def test_full_hogql_query_view(self): @@ -498,6 +498,7 @@ def test_full_hogql_query_view(self): flush_persons_and_events() with freeze_time("2020-01-10 12:14:00"): + self.client.post( f"/api/projects/{self.team.id}/warehouse_saved_queries/", { @@ -510,7 +511,7 @@ def test_full_hogql_query_view(self): ) query = HogQLQuery(query="select * from event_view") api_response = self.client.post(f"/api/projects/{self.team.id}/query/", {"query": query.dict()}).json() - query.response = HogQLQueryResponse.model_validate(api_response) + query.response = HogQLQueryResponse.parse_obj(api_response) self.assertEqual(query.response.results and len(query.response.results), 4) self.assertEqual( diff --git a/posthog/hogql/constants.py b/posthog/hogql/constants.py index fc01500f79e83..a5c7d35f13675 100644 --- a/posthog/hogql/constants.py +++ b/posthog/hogql/constants.py @@ -1,7 +1,7 @@ from datetime import date, datetime from typing import Optional, Literal, TypeAlias, Tuple, List from uuid import UUID -from pydantic import ConfigDict, BaseModel +from pydantic import BaseModel, Extra ConstantDataType: TypeAlias = Literal[ "int", "float", "str", "bool", "array", "tuple", "date", "datetime", "uuid", "unknown" @@ -24,7 +24,8 @@ # Settings applied on top of all HogQL queries. class HogQLSettings(BaseModel): - model_config = ConfigDict(extra="forbid") + class Config: + extra = Extra.forbid readonly: Optional[int] = 2 max_execution_time: Optional[int] = 60 diff --git a/posthog/hogql/database/database.py b/posthog/hogql/database/database.py index 5cddd747c3429..4f5cea81d1425 100644 --- a/posthog/hogql/database/database.py +++ b/posthog/hogql/database/database.py @@ -1,6 +1,6 @@ -from typing import Any, ClassVar, Dict, List, Literal, Optional, TypedDict +from typing import Any, Dict, List, Literal, Optional, TypedDict from zoneinfo import ZoneInfo, ZoneInfoNotFoundError -from pydantic import ConfigDict, BaseModel +from pydantic import BaseModel, Extra from posthog.hogql.database.models import ( FieldTraverser, @@ -33,7 +33,8 @@ class Database(BaseModel): - model_config = ConfigDict(extra="allow") + class Config: + extra = Extra.allow # Users can query from the tables below events: EventsTable = EventsTable() @@ -57,7 +58,7 @@ class Database(BaseModel): numbers: NumbersTable = NumbersTable() # clunky: keep table names in sync with above - _table_names: ClassVar[List[str]] = [ + _table_names: List[str] = [ "events", "groups", "person", @@ -181,7 +182,7 @@ class SerializedField(_SerializedFieldBase, total=False): def serialize_database(database: Database) -> Dict[str, List[SerializedField]]: tables: Dict[str, List[SerializedField]] = {} - for table_key in database.model_fields.keys(): + for table_key in database.__fields__.keys(): field_input: Dict[str, Any] = {} table = getattr(database, table_key, None) if isinstance(table, FunctionCallTable): diff --git a/posthog/hogql/database/models.py b/posthog/hogql/database/models.py index e5283eb68142e..dc5b74724b96f 100644 --- a/posthog/hogql/database/models.py +++ b/posthog/hogql/database/models.py @@ -1,5 +1,5 @@ from typing import Any, Callable, Dict, List, Optional, TYPE_CHECKING -from pydantic import ConfigDict, BaseModel +from pydantic import BaseModel, Extra from posthog.hogql.errors import HogQLException, NotImplementedException @@ -16,7 +16,8 @@ class DatabaseField(FieldOrTable): Base class for a field in a database table. """ - model_config = ConfigDict(extra="forbid") + class Config: + extra = Extra.forbid name: str array: Optional[bool] = None @@ -56,14 +57,17 @@ class BooleanDatabaseField(DatabaseField): class FieldTraverser(FieldOrTable): - model_config = ConfigDict(extra="forbid") + class Config: + extra = Extra.forbid chain: List[str] class Table(FieldOrTable): fields: Dict[str, FieldOrTable] - model_config = ConfigDict(extra="forbid") + + class Config: + extra = Extra.forbid def has_field(self, name: str) -> bool: return name in self.fields @@ -98,7 +102,8 @@ def get_asterisk(self): class LazyJoin(FieldOrTable): - model_config = ConfigDict(extra="forbid") + class Config: + extra = Extra.forbid join_function: Callable[[str, str, Dict[str, Any]], Any] join_table: Table @@ -110,7 +115,8 @@ class LazyTable(Table): A table that is replaced with a subquery returned from `lazy_select(requested_fields: Dict[name, chain])` """ - model_config = ConfigDict(extra="forbid") + class Config: + extra = Extra.forbid def lazy_select(self, requested_fields: Dict[str, List[str]]) -> Any: raise NotImplementedException("LazyTable.lazy_select not overridden") @@ -121,7 +127,8 @@ class VirtualTable(Table): A nested table that reuses the parent for storage. E.g. events.person.* fields with PoE enabled. """ - model_config = ConfigDict(extra="forbid") + class Config: + extra = Extra.forbid class FunctionCallTable(Table): diff --git a/posthog/hogql/database/schema/numbers.py b/posthog/hogql/database/schema/numbers.py index 01c09ac66d797..6db50440cda9e 100644 --- a/posthog/hogql/database/schema/numbers.py +++ b/posthog/hogql/database/schema/numbers.py @@ -1,4 +1,4 @@ -from typing import Dict, Optional +from typing import Dict from posthog.hogql.database.models import ( IntegerDatabaseField, @@ -14,9 +14,9 @@ class NumbersTable(FunctionCallTable): fields: Dict[str, FieldOrTable] = NUMBERS_TABLE_FIELDS - name: str = "numbers" - min_args: Optional[int] = 1 - max_args: Optional[int] = 2 + name = "numbers" + min_args = 1 + max_args = 2 def to_printed_clickhouse(self, context): return "numbers" diff --git a/posthog/hogql/test/test_metadata.py b/posthog/hogql/test/test_metadata.py index 54dbcb17a9eb6..584dbfab67d0d 100644 --- a/posthog/hogql/test/test_metadata.py +++ b/posthog/hogql/test/test_metadata.py @@ -8,12 +8,10 @@ class TestMetadata(ClickhouseTestMixin, APIBaseTest): maxDiff = None def _expr(self, query: str) -> HogQLMetadataResponse: - return get_hogql_metadata(query=HogQLMetadata(kind="HogQLMetadata", expr=query, response=None), team=self.team) + return get_hogql_metadata(query=HogQLMetadata(expr=query), team=self.team) def _select(self, query: str) -> HogQLMetadataResponse: - return get_hogql_metadata( - query=HogQLMetadata(kind="HogQLMetadata", select=query, response=None), team=self.team - ) + return get_hogql_metadata(query=HogQLMetadata(select=query), team=self.team) def test_metadata_valid_expr_select(self): metadata = self._expr("select 1") diff --git a/posthog/hogql/test/test_query.py b/posthog/hogql/test/test_query.py index d45a1edcb9672..cb7d19f9df337 100644 --- a/posthog/hogql/test/test_query.py +++ b/posthog/hogql/test/test_query.py @@ -1446,7 +1446,7 @@ def test_hogql_query_filters(self): ) query = "SELECT event, distinct_id from events WHERE distinct_id={distinct_id} and {filters}" filters = HogQLFilters( - properties=[EventPropertyFilter(key="index", operator="exact", value="4", type="event")] + properties=[EventPropertyFilter(key="index", operator="exact", value=4, type="event")] ) placeholders = {"distinct_id": ast.Constant(value=random_uuid)} response = execute_hogql_query(query, team=self.team, filters=filters, placeholders=placeholders) diff --git a/posthog/hogql_queries/lifecycle_query_runner.py b/posthog/hogql_queries/lifecycle_query_runner.py index ea43b3cd69aa0..2b970bb95156c 100644 --- a/posthog/hogql_queries/lifecycle_query_runner.py +++ b/posthog/hogql_queries/lifecycle_query_runner.py @@ -22,7 +22,7 @@ def __init__(self, query: LifecycleQuery | Dict[str, Any], team: Team, timings: if isinstance(query, LifecycleQuery): self.query = query else: - self.query = LifecycleQuery.model_validate(query) + self.query = LifecycleQuery.parse_obj(query) def to_query(self) -> ast.SelectQuery: placeholders = { diff --git a/posthog/schema.py b/posthog/schema.py index a1da2403d0d8f..b988b9618e0ef 100644 --- a/posthog/schema.py +++ b/posthog/schema.py @@ -6,8 +6,7 @@ from enum import Enum from typing import Any, Dict, List, Optional, Union -from pydantic import BaseModel, ConfigDict, Field, RootModel -from typing_extensions import Literal +from pydantic import BaseModel, Extra, Field class MathGroupTypeIndex(float, Enum): @@ -63,12 +62,12 @@ class ChartDisplayType(str, Enum): class CohortPropertyFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - key: Literal["id"] = "id" + class Config: + extra = Extra.forbid + + key: str = Field("id", const=True) label: Optional[str] = None - type: Literal["cohort"] = "cohort" + type: str = Field("cohort", const=True) value: float @@ -83,9 +82,9 @@ class CountPerActorMathType(str, Enum): class DatabaseSchemaQueryResponseField(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + chain: Optional[List[str]] = None fields: Optional[List[str]] = None key: str @@ -94,9 +93,9 @@ class DatabaseSchemaQueryResponseField(BaseModel): class DateRange(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + date_from: Optional[str] = None date_to: Optional[str] = None @@ -109,9 +108,9 @@ class Key(str, Enum): class ElementType(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + attr_class: Optional[List[str]] = None attr_id: Optional[str] = None attributes: Dict[str, str] @@ -124,9 +123,9 @@ class ElementType(BaseModel): class EmptyPropertyFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + key: Optional[Any] = None operator: Optional[Any] = None type: Optional[Any] = None @@ -140,18 +139,18 @@ class EntityType(str, Enum): class Person(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + distinct_ids: List[str] is_identified: Optional[bool] = None properties: Dict[str, Any] class EventType(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + distinct_id: str elements: List[ElementType] elements_chain: Optional[str] = None @@ -163,10 +162,18 @@ class EventType(BaseModel): uuid: Optional[str] = None +class MathGroupTypeIndex1(float, Enum): + number_0 = 0 + number_1 = 1 + number_2 = 2 + number_3 = 3 + number_4 = 4 + + class Response(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + next: Optional[str] = None results: List[EventType] @@ -197,9 +204,9 @@ class FunnelPathType(str, Enum): class FunnelStepRangeEntityFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + custom_name: Optional[str] = None funnel_from_step: Optional[float] = None funnel_to_step: Optional[float] = None @@ -227,9 +234,9 @@ class FunnelCorrelationPersonConverted(str, Enum): class HogQLNotice(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + end: Optional[float] = None fix: Optional[str] = None message: str @@ -251,9 +258,9 @@ class LifecycleToggle(str, Enum): class PathCleaningFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + alias: Optional[str] = None regex: Optional[str] = None @@ -266,9 +273,9 @@ class PathType(str, Enum): class PathsFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + edge_limit: Optional[float] = None end_point: Optional[str] = None exclude_events: Optional[List[str]] = None @@ -323,21 +330,21 @@ class PropertyOperator(str, Enum): class QueryTiming(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + k: str = Field(..., description="Key. Shortened to 'k' to save on data.") t: float = Field(..., description="Time in seconds. Shortened to 't' to save on data.") class RecordingDurationFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - key: Literal["duration"] = "duration" + class Config: + extra = Extra.forbid + + key: str = Field("duration", const=True) label: Optional[str] = None operator: PropertyOperator - type: Literal["recording"] = "recording" + type: str = Field("recording", const=True) value: float @@ -359,62 +366,58 @@ class RetentionType(str, Enum): class SavedInsightNode(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + allowSorting: Optional[bool] = Field( - default=None, description="Can the user click on column headers to sort the table? (default: true)" - ) - embedded: Optional[bool] = Field(default=None, description="Query is embedded inside another bordered component") - expandable: Optional[bool] = Field( - default=None, description="Can expand row to show raw event data (default: true)" - ) - full: Optional[bool] = Field( - default=None, description="Show with most visual options enabled. Used in insight scene." + None, description="Can the user click on column headers to sort the table? (default: true)" ) - kind: Literal["SavedInsightNode"] = "SavedInsightNode" - propertiesViaUrl: Optional[bool] = Field(default=None, description="Link properties via the URL (default: false)") + embedded: Optional[bool] = Field(None, description="Query is embedded inside another bordered component") + expandable: Optional[bool] = Field(None, description="Can expand row to show raw event data (default: true)") + full: Optional[bool] = Field(None, description="Show with most visual options enabled. Used in insight scene.") + kind: str = Field("SavedInsightNode", const=True) + propertiesViaUrl: Optional[bool] = Field(None, description="Link properties via the URL (default: false)") shortId: str - showActions: Optional[bool] = Field(default=None, description="Show the kebab menu at the end of the row") + showActions: Optional[bool] = Field(None, description="Show the kebab menu at the end of the row") showColumnConfigurator: Optional[bool] = Field( - default=None, description="Show a button to configure the table's columns if possible" + None, description="Show a button to configure the table's columns if possible" ) showCorrelationTable: Optional[bool] = None - showDateRange: Optional[bool] = Field(default=None, description="Show date range selector") - showElapsedTime: Optional[bool] = Field(default=None, description="Show the time it takes to run a query") + showDateRange: Optional[bool] = Field(None, description="Show date range selector") + showElapsedTime: Optional[bool] = Field(None, description="Show the time it takes to run a query") showEventFilter: Optional[bool] = Field( - default=None, description="Include an event filter above the table (EventsNode only)" + None, description="Include an event filter above the table (EventsNode only)" ) - showExport: Optional[bool] = Field(default=None, description="Show the export button") + showExport: Optional[bool] = Field(None, description="Show the export button") showFilters: Optional[bool] = None showHeader: Optional[bool] = None - showHogQLEditor: Optional[bool] = Field(default=None, description="Include a HogQL query editor above HogQL tables") + showHogQLEditor: Optional[bool] = Field(None, description="Include a HogQL query editor above HogQL tables") showLastComputation: Optional[bool] = None showLastComputationRefresh: Optional[bool] = None showOpenEditorButton: Optional[bool] = Field( - default=None, description="Show a button to open the current query as a new insight. (default: true)" + None, description="Show a button to open the current query as a new insight. (default: true)" ) showPersistentColumnConfigurator: Optional[bool] = Field( - default=None, description="Show a button to configure and persist the table's default columns if possible" + None, description="Show a button to configure and persist the table's default columns if possible" ) - showPropertyFilter: Optional[bool] = Field(default=None, description="Include a property filter above the table") - showReload: Optional[bool] = Field(default=None, description="Show a reload button") + showPropertyFilter: Optional[bool] = Field(None, description="Include a property filter above the table") + showReload: Optional[bool] = Field(None, description="Show a reload button") showResults: Optional[bool] = None - showResultsTable: Optional[bool] = Field(default=None, description="Show a results table") - showSavedQueries: Optional[bool] = Field(default=None, description="Shows a list of saved queries") - showSearch: Optional[bool] = Field(default=None, description="Include a free text search field (PersonsNode only)") + showResultsTable: Optional[bool] = Field(None, description="Show a results table") + showSavedQueries: Optional[bool] = Field(None, description="Shows a list of saved queries") + showSearch: Optional[bool] = Field(None, description="Include a free text search field (PersonsNode only)") showTable: Optional[bool] = None - showTimings: Optional[bool] = Field(default=None, description="Show a detailed query timing breakdown") + showTimings: Optional[bool] = Field(None, description="Show a detailed query timing breakdown") class SessionPropertyFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - key: Literal["$session_duration"] = "$session_duration" + class Config: + extra = Extra.forbid + + key: str = Field("$session_duration", const=True) label: Optional[str] = None operator: PropertyOperator - type: Literal["session"] = "session" + type: str = Field("session", const=True) value: Optional[Union[str, float, List[Union[str, float]]]] = None @@ -431,9 +434,9 @@ class StepOrderValue(str, Enum): class StickinessFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + compare: Optional[bool] = None display: Optional[ChartDisplayType] = None hidden_legend_indexes: Optional[List[float]] = None @@ -444,16 +447,16 @@ class StickinessFilter(BaseModel): class TimeToSeeDataSessionsQueryResponse(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + results: List[Dict[str, Any]] class TrendsFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + aggregation_axis_format: Optional[AggregationAxisFormat] = None aggregation_axis_postfix: Optional[str] = None aggregation_axis_prefix: Optional[str] = None @@ -470,18 +473,18 @@ class TrendsFilter(BaseModel): class Breakdown(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + normalize_url: Optional[bool] = None property: Union[str, float] type: BreakdownType class BreakdownFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + breakdown: Optional[Union[str, float, List[Union[str, float]]]] = None breakdown_group_type_index: Optional[float] = None breakdown_histogram_bin_count: Optional[float] = None @@ -491,31 +494,31 @@ class BreakdownFilter(BaseModel): class ElementPropertyFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + key: Key label: Optional[str] = None operator: PropertyOperator - type: Literal["element"] = "element" + type: str = Field("element", const=True) value: Optional[Union[str, float, List[Union[str, float]]]] = None class EventPropertyFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + key: str label: Optional[str] = None operator: PropertyOperator - type: Literal["event"] = Field(default="event", description="Event properties") + type: str = Field("event", const=True, description="Event properties") value: Optional[Union[str, float, List[Union[str, float]]]] = None class EventsQueryResponse(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + columns: List hasMore: Optional[bool] = None results: List[List] @@ -524,20 +527,20 @@ class EventsQueryResponse(BaseModel): class FeaturePropertyFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + key: str label: Optional[str] = None operator: PropertyOperator - type: Literal["feature"] = Field(default="feature", description='Event property with "$feature/" prepended') + type: str = Field("feature", const=True, description='Event property with "$feature/" prepended') value: Optional[Union[str, float, List[Union[str, float]]]] = None class FunnelsFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + bin_count: Optional[Union[float, str]] = None breakdown_attribution_type: Optional[BreakdownAttributionType] = None breakdown_attribution_value: Optional[float] = None @@ -563,21 +566,21 @@ class FunnelsFilter(BaseModel): class GroupPropertyFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + group_type_index: Optional[float] = None key: str label: Optional[str] = None operator: PropertyOperator - type: Literal["group"] = "group" + type: str = Field("group", const=True) value: Optional[Union[str, float, List[Union[str, float]]]] = None class HogQLMetadataResponse(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + errors: List[HogQLNotice] inputExpr: Optional[str] = None inputSelect: Optional[str] = None @@ -588,19 +591,19 @@ class HogQLMetadataResponse(BaseModel): class HogQLPropertyFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + key: str label: Optional[str] = None - type: Literal["hogql"] = "hogql" + type: str = Field("hogql", const=True) value: Optional[Union[str, float, List[Union[str, float]]]] = None class HogQLQueryResponse(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + clickhouse: Optional[str] = None columns: Optional[List] = None hogql: Optional[str] = None @@ -611,37 +614,37 @@ class HogQLQueryResponse(BaseModel): class LifecycleFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + show_values_on_series: Optional[bool] = None shown_as: Optional[ShownAsValue] = None toggledLifecycles: Optional[List[LifecycleToggle]] = None class LifecycleQueryResponse(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + result: List[Dict[str, Any]] timings: Optional[List[QueryTiming]] = None class PersonPropertyFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + key: str label: Optional[str] = None operator: PropertyOperator - type: Literal["person"] = Field(default="person", description="Person properties") + type: str = Field("person", const=True, description="Person properties") value: Optional[Union[str, float, List[Union[str, float]]]] = None class RetentionFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + period: Optional[RetentionPeriod] = None retention_reference: Optional[RetentionReference] = None retention_type: Optional[RetentionType] = None @@ -651,31 +654,31 @@ class RetentionFilter(BaseModel): class TimeToSeeDataSessionsQuery(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - dateRange: Optional[DateRange] = Field(default=None, description="Date range for the query") - kind: Literal["TimeToSeeDataSessionsQuery"] = "TimeToSeeDataSessionsQuery" - response: Optional[TimeToSeeDataSessionsQueryResponse] = Field(default=None, description="Cached query response") - teamId: Optional[float] = Field(default=None, description="Project to filter on. Defaults to current project") + class Config: + extra = Extra.forbid + + dateRange: Optional[DateRange] = Field(None, description="Date range for the query") + kind: str = Field("TimeToSeeDataSessionsQuery", const=True) + response: Optional[TimeToSeeDataSessionsQueryResponse] = Field(None, description="Cached query response") + teamId: Optional[float] = Field(None, description="Project to filter on. Defaults to current project") class DatabaseSchemaQuery(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - kind: Literal["DatabaseSchemaQuery"] = "DatabaseSchemaQuery" + class Config: + extra = Extra.forbid + + kind: str = Field("DatabaseSchemaQuery", const=True) response: Optional[Dict[str, List[DatabaseSchemaQueryResponseField]]] = Field( - default=None, description="Cached query response" + None, description="Cached query response" ) class EventsNode(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + custom_name: Optional[str] = None - event: Optional[str] = Field(default=None, description="The event or `null` for all events.") + event: Optional[str] = Field(None, description="The event or `null` for all events.") fixedProperties: Optional[ List[ Union[ @@ -692,19 +695,17 @@ class EventsNode(BaseModel): ] ] ] = Field( - default=None, + None, description="Fixed properties in the query, can't be edited in the interface (e.g. scoping down by person)", ) - kind: Literal["EventsNode"] = "EventsNode" + kind: str = Field("EventsNode", const=True) limit: Optional[float] = None - math: Optional[ - Union[BaseMathType, PropertyMathType, CountPerActorMathType, Literal["unique_group"], Literal["hogql"]] - ] = None - math_group_type_index: Optional[MathGroupTypeIndex] = None + math: Optional[Union[BaseMathType, PropertyMathType, CountPerActorMathType, str, str]] = None + math_group_type_index: Optional[MathGroupTypeIndex1] = None math_hogql: Optional[str] = None math_property: Optional[str] = None name: Optional[str] = None - orderBy: Optional[List[str]] = Field(default=None, description="Columns to order by") + orderBy: Optional[List[str]] = Field(None, description="Columns to order by") properties: Optional[ List[ Union[ @@ -720,18 +721,18 @@ class EventsNode(BaseModel): EmptyPropertyFilter, ] ] - ] = Field(default=None, description="Properties configurable in the interface") - response: Optional[Response] = Field(default=None, description="Return a limited set of data") + ] = Field(None, description="Properties configurable in the interface") + response: Optional[Response] = Field(None, description="Return a limited set of data") class EventsQuery(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - actionId: Optional[int] = Field(default=None, description="Show events matching a given action") - after: Optional[str] = Field(default=None, description="Only fetch events that happened after this timestamp") - before: Optional[str] = Field(default=None, description="Only fetch events that happened before this timestamp") - event: Optional[str] = Field(default=None, description="Limit to events matching this string") + class Config: + extra = Extra.forbid + + actionId: Optional[int] = Field(None, description="Show events matching a given action") + after: Optional[str] = Field(None, description="Only fetch events that happened after this timestamp") + before: Optional[str] = Field(None, description="Only fetch events that happened before this timestamp") + event: Optional[str] = Field(None, description="Limit to events matching this string") fixedProperties: Optional[ List[ Union[ @@ -748,14 +749,14 @@ class EventsQuery(BaseModel): ] ] ] = Field( - default=None, + None, description="Fixed properties in the query, can't be edited in the interface (e.g. scoping down by person)", ) - kind: Literal["EventsQuery"] = "EventsQuery" - limit: Optional[int] = Field(default=None, description="Number of rows to return") - offset: Optional[int] = Field(default=None, description="Number of rows to skip before returning rows") - orderBy: Optional[List[str]] = Field(default=None, description="Columns to order by") - personId: Optional[str] = Field(default=None, description="Show events for a given person") + kind: str = Field("EventsQuery", const=True) + limit: Optional[int] = Field(None, description="Number of rows to return") + offset: Optional[int] = Field(None, description="Number of rows to skip before returning rows") + orderBy: Optional[List[str]] = Field(None, description="Columns to order by") + personId: Optional[str] = Field(None, description="Show events for a given person") properties: Optional[ List[ Union[ @@ -771,16 +772,16 @@ class EventsQuery(BaseModel): EmptyPropertyFilter, ] ] - ] = Field(default=None, description="Properties configurable in the interface") - response: Optional[EventsQueryResponse] = Field(default=None, description="Cached query response") + ] = Field(None, description="Properties configurable in the interface") + response: Optional[EventsQueryResponse] = Field(None, description="Cached query response") select: List[str] = Field(..., description="Return a limited set of data. Required.") - where: Optional[List[str]] = Field(default=None, description="HogQL filters to apply on returned data") + where: Optional[List[str]] = Field(None, description="HogQL filters to apply on returned data") class HogQLFilters(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + dateRange: Optional[DateRange] = None properties: Optional[ List[ @@ -801,30 +802,30 @@ class HogQLFilters(BaseModel): class HogQLMetadata(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + expr: Optional[str] = None filters: Optional[HogQLFilters] = None - kind: Literal["HogQLMetadata"] = "HogQLMetadata" - response: Optional[HogQLMetadataResponse] = Field(default=None, description="Cached query response") + kind: str = Field("HogQLMetadata", const=True) + response: Optional[HogQLMetadataResponse] = Field(None, description="Cached query response") select: Optional[str] = None class HogQLQuery(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + filters: Optional[HogQLFilters] = None - kind: Literal["HogQLQuery"] = "HogQLQuery" + kind: str = Field("HogQLQuery", const=True) query: str - response: Optional[HogQLQueryResponse] = Field(default=None, description="Cached query response") + response: Optional[HogQLQueryResponse] = Field(None, description="Cached query response") class PersonsNode(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + cohort: Optional[float] = None distinctId: Optional[str] = None fixedProperties: Optional[ @@ -843,10 +844,10 @@ class PersonsNode(BaseModel): ] ] ] = Field( - default=None, + None, description="Fixed properties in the query, can't be edited in the interface (e.g. scoping down by person)", ) - kind: Literal["PersonsNode"] = "PersonsNode" + kind: str = Field("PersonsNode", const=True) limit: Optional[float] = None offset: Optional[float] = None properties: Optional[ @@ -864,15 +865,15 @@ class PersonsNode(BaseModel): EmptyPropertyFilter, ] ] - ] = Field(default=None, description="Properties configurable in the interface") - response: Optional[Dict[str, Any]] = Field(default=None, description="Cached query response") + ] = Field(None, description="Properties configurable in the interface") + response: Optional[Dict[str, Any]] = Field(None, description="Cached query response") search: Optional[str] = None class PropertyGroupFilterValue(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + type: FilterLogicalOperator values: List[ Union[ @@ -894,9 +895,9 @@ class PropertyGroupFilterValue(BaseModel): class ActionsNode(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + custom_name: Optional[str] = None fixedProperties: Optional[ List[ @@ -914,14 +915,12 @@ class ActionsNode(BaseModel): ] ] ] = Field( - default=None, + None, description="Fixed properties in the query, can't be edited in the interface (e.g. scoping down by person)", ) id: float - kind: Literal["ActionsNode"] = "ActionsNode" - math: Optional[ - Union[BaseMathType, PropertyMathType, CountPerActorMathType, Literal["unique_group"], Literal["hogql"]] - ] = None + kind: str = Field("ActionsNode", const=True) + math: Optional[Union[BaseMathType, PropertyMathType, CountPerActorMathType, str, str]] = None math_group_type_index: Optional[MathGroupTypeIndex] = None math_hogql: Optional[str] = None math_property: Optional[str] = None @@ -941,76 +940,74 @@ class ActionsNode(BaseModel): EmptyPropertyFilter, ] ] - ] = Field(default=None, description="Properties configurable in the interface") - response: Optional[Dict[str, Any]] = Field(default=None, description="Cached query response") + ] = Field(None, description="Properties configurable in the interface") + response: Optional[Dict[str, Any]] = Field(None, description="Cached query response") class DataTableNode(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + allowSorting: Optional[bool] = Field( - default=None, description="Can the user click on column headers to sort the table? (default: true)" + None, description="Can the user click on column headers to sort the table? (default: true)" ) columns: Optional[List[str]] = Field( - default=None, description="Columns shown in the table, unless the `source` provides them." - ) - embedded: Optional[bool] = Field(default=None, description="Uses the embedded version of LemonTable") - expandable: Optional[bool] = Field( - default=None, description="Can expand row to show raw event data (default: true)" + None, description="Columns shown in the table, unless the `source` provides them." ) - full: Optional[bool] = Field(default=None, description="Show with most visual options enabled. Used in scenes.") + embedded: Optional[bool] = Field(None, description="Uses the embedded version of LemonTable") + expandable: Optional[bool] = Field(None, description="Can expand row to show raw event data (default: true)") + full: Optional[bool] = Field(None, description="Show with most visual options enabled. Used in scenes.") hiddenColumns: Optional[List[str]] = Field( - default=None, description="Columns that aren't shown in the table, even if in columns or returned data" + None, description="Columns that aren't shown in the table, even if in columns or returned data" ) - kind: Literal["DataTableNode"] = "DataTableNode" - propertiesViaUrl: Optional[bool] = Field(default=None, description="Link properties via the URL (default: false)") - showActions: Optional[bool] = Field(default=None, description="Show the kebab menu at the end of the row") + kind: str = Field("DataTableNode", const=True) + propertiesViaUrl: Optional[bool] = Field(None, description="Link properties via the URL (default: false)") + showActions: Optional[bool] = Field(None, description="Show the kebab menu at the end of the row") showColumnConfigurator: Optional[bool] = Field( - default=None, description="Show a button to configure the table's columns if possible" + None, description="Show a button to configure the table's columns if possible" ) - showDateRange: Optional[bool] = Field(default=None, description="Show date range selector") - showElapsedTime: Optional[bool] = Field(default=None, description="Show the time it takes to run a query") + showDateRange: Optional[bool] = Field(None, description="Show date range selector") + showElapsedTime: Optional[bool] = Field(None, description="Show the time it takes to run a query") showEventFilter: Optional[bool] = Field( - default=None, description="Include an event filter above the table (EventsNode only)" + None, description="Include an event filter above the table (EventsNode only)" ) - showExport: Optional[bool] = Field(default=None, description="Show the export button") - showHogQLEditor: Optional[bool] = Field(default=None, description="Include a HogQL query editor above HogQL tables") + showExport: Optional[bool] = Field(None, description="Show the export button") + showHogQLEditor: Optional[bool] = Field(None, description="Include a HogQL query editor above HogQL tables") showOpenEditorButton: Optional[bool] = Field( - default=None, description="Show a button to open the current query as a new insight. (default: true)" + None, description="Show a button to open the current query as a new insight. (default: true)" ) showPersistentColumnConfigurator: Optional[bool] = Field( - default=None, description="Show a button to configure and persist the table's default columns if possible" - ) - showPropertyFilter: Optional[bool] = Field(default=None, description="Include a property filter above the table") - showReload: Optional[bool] = Field(default=None, description="Show a reload button") - showResultsTable: Optional[bool] = Field(default=None, description="Show a results table") - showSavedQueries: Optional[bool] = Field(default=None, description="Shows a list of saved queries") - showSearch: Optional[bool] = Field(default=None, description="Include a free text search field (PersonsNode only)") - showTimings: Optional[bool] = Field(default=None, description="Show a detailed query timing breakdown") + None, description="Show a button to configure and persist the table's default columns if possible" + ) + showPropertyFilter: Optional[bool] = Field(None, description="Include a property filter above the table") + showReload: Optional[bool] = Field(None, description="Show a reload button") + showResultsTable: Optional[bool] = Field(None, description="Show a results table") + showSavedQueries: Optional[bool] = Field(None, description="Shows a list of saved queries") + showSearch: Optional[bool] = Field(None, description="Include a free text search field (PersonsNode only)") + showTimings: Optional[bool] = Field(None, description="Show a detailed query timing breakdown") source: Union[EventsNode, EventsQuery, PersonsNode, HogQLQuery, TimeToSeeDataSessionsQuery] = Field( ..., description="Source of the events" ) class PropertyGroupFilter(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) + class Config: + extra = Extra.forbid + type: FilterLogicalOperator values: List[PropertyGroupFilterValue] class RetentionQuery(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - aggregation_group_type_index: Optional[float] = Field(default=None, description="Groups aggregation") - dateRange: Optional[DateRange] = Field(default=None, description="Date range for the query") + class Config: + extra = Extra.forbid + + aggregation_group_type_index: Optional[float] = Field(None, description="Groups aggregation") + dateRange: Optional[DateRange] = Field(None, description="Date range for the query") filterTestAccounts: Optional[bool] = Field( - default=None, description="Exclude internal and test users by applying the respective filters" + None, description="Exclude internal and test users by applying the respective filters" ) - kind: Literal["RetentionQuery"] = "RetentionQuery" + kind: str = Field("RetentionQuery", const=True) properties: Optional[ Union[ List[ @@ -1029,26 +1026,24 @@ class RetentionQuery(BaseModel): ], PropertyGroupFilter, ] - ] = Field(default=None, description="Property filters for all series") - retentionFilter: Optional[RetentionFilter] = Field( - default=None, description="Properties specific to the retention insight" - ) - samplingFactor: Optional[float] = Field(default=None, description="Sampling rate") + ] = Field(None, description="Property filters for all series") + retentionFilter: Optional[RetentionFilter] = Field(None, description="Properties specific to the retention insight") + samplingFactor: Optional[float] = Field(None, description="Sampling rate") class StickinessQuery(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - aggregation_group_type_index: Optional[float] = Field(default=None, description="Groups aggregation") - dateRange: Optional[DateRange] = Field(default=None, description="Date range for the query") + class Config: + extra = Extra.forbid + + aggregation_group_type_index: Optional[float] = Field(None, description="Groups aggregation") + dateRange: Optional[DateRange] = Field(None, description="Date range for the query") filterTestAccounts: Optional[bool] = Field( - default=None, description="Exclude internal and test users by applying the respective filters" + None, description="Exclude internal and test users by applying the respective filters" ) interval: Optional[IntervalType] = Field( - default=None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" + None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" ) - kind: Literal["StickinessQuery"] = "StickinessQuery" + kind: str = Field("StickinessQuery", const=True) properties: Optional[ Union[ List[ @@ -1067,28 +1062,28 @@ class StickinessQuery(BaseModel): ], PropertyGroupFilter, ] - ] = Field(default=None, description="Property filters for all series") - samplingFactor: Optional[float] = Field(default=None, description="Sampling rate") + ] = Field(None, description="Property filters for all series") + samplingFactor: Optional[float] = Field(None, description="Sampling rate") series: List[Union[EventsNode, ActionsNode]] = Field(..., description="Events and actions to include") stickinessFilter: Optional[StickinessFilter] = Field( - default=None, description="Properties specific to the stickiness insight" + None, description="Properties specific to the stickiness insight" ) class TrendsQuery(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - aggregation_group_type_index: Optional[float] = Field(default=None, description="Groups aggregation") - breakdown: Optional[BreakdownFilter] = Field(default=None, description="Breakdown of the events and actions") - dateRange: Optional[DateRange] = Field(default=None, description="Date range for the query") + class Config: + extra = Extra.forbid + + aggregation_group_type_index: Optional[float] = Field(None, description="Groups aggregation") + breakdown: Optional[BreakdownFilter] = Field(None, description="Breakdown of the events and actions") + dateRange: Optional[DateRange] = Field(None, description="Date range for the query") filterTestAccounts: Optional[bool] = Field( - default=None, description="Exclude internal and test users by applying the respective filters" + None, description="Exclude internal and test users by applying the respective filters" ) interval: Optional[IntervalType] = Field( - default=None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" + None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" ) - kind: Literal["TrendsQuery"] = "TrendsQuery" + kind: str = Field("TrendsQuery", const=True) properties: Optional[ Union[ List[ @@ -1107,29 +1102,27 @@ class TrendsQuery(BaseModel): ], PropertyGroupFilter, ] - ] = Field(default=None, description="Property filters for all series") - samplingFactor: Optional[float] = Field(default=None, description="Sampling rate") + ] = Field(None, description="Property filters for all series") + samplingFactor: Optional[float] = Field(None, description="Sampling rate") series: List[Union[EventsNode, ActionsNode]] = Field(..., description="Events and actions to include") - trendsFilter: Optional[TrendsFilter] = Field(default=None, description="Properties specific to the trends insight") + trendsFilter: Optional[TrendsFilter] = Field(None, description="Properties specific to the trends insight") class FunnelsQuery(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - aggregation_group_type_index: Optional[float] = Field(default=None, description="Groups aggregation") - breakdown: Optional[BreakdownFilter] = Field(default=None, description="Breakdown of the events and actions") - dateRange: Optional[DateRange] = Field(default=None, description="Date range for the query") + class Config: + extra = Extra.forbid + + aggregation_group_type_index: Optional[float] = Field(None, description="Groups aggregation") + breakdown: Optional[BreakdownFilter] = Field(None, description="Breakdown of the events and actions") + dateRange: Optional[DateRange] = Field(None, description="Date range for the query") filterTestAccounts: Optional[bool] = Field( - default=None, description="Exclude internal and test users by applying the respective filters" - ) - funnelsFilter: Optional[FunnelsFilter] = Field( - default=None, description="Properties specific to the funnels insight" + None, description="Exclude internal and test users by applying the respective filters" ) + funnelsFilter: Optional[FunnelsFilter] = Field(None, description="Properties specific to the funnels insight") interval: Optional[IntervalType] = Field( - default=None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" + None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" ) - kind: Literal["FunnelsQuery"] = "FunnelsQuery" + kind: str = Field("FunnelsQuery", const=True) properties: Optional[ Union[ List[ @@ -1148,27 +1141,25 @@ class FunnelsQuery(BaseModel): ], PropertyGroupFilter, ] - ] = Field(default=None, description="Property filters for all series") - samplingFactor: Optional[float] = Field(default=None, description="Sampling rate") + ] = Field(None, description="Property filters for all series") + samplingFactor: Optional[float] = Field(None, description="Sampling rate") series: List[Union[EventsNode, ActionsNode]] = Field(..., description="Events and actions to include") class LifecycleQuery(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - aggregation_group_type_index: Optional[float] = Field(default=None, description="Groups aggregation") - dateRange: Optional[DateRange] = Field(default=None, description="Date range for the query") + class Config: + extra = Extra.forbid + + aggregation_group_type_index: Optional[float] = Field(None, description="Groups aggregation") + dateRange: Optional[DateRange] = Field(None, description="Date range for the query") filterTestAccounts: Optional[bool] = Field( - default=None, description="Exclude internal and test users by applying the respective filters" + None, description="Exclude internal and test users by applying the respective filters" ) interval: Optional[IntervalType] = Field( - default=None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" - ) - kind: Literal["LifecycleQuery"] = "LifecycleQuery" - lifecycleFilter: Optional[LifecycleFilter] = Field( - default=None, description="Properties specific to the lifecycle insight" + None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" ) + kind: str = Field("LifecycleQuery", const=True) + lifecycleFilter: Optional[LifecycleFilter] = Field(None, description="Properties specific to the lifecycle insight") properties: Optional[ Union[ List[ @@ -1187,23 +1178,23 @@ class LifecycleQuery(BaseModel): ], PropertyGroupFilter, ] - ] = Field(default=None, description="Property filters for all series") + ] = Field(None, description="Property filters for all series") response: Optional[LifecycleQueryResponse] = None - samplingFactor: Optional[float] = Field(default=None, description="Sampling rate") + samplingFactor: Optional[float] = Field(None, description="Sampling rate") series: List[Union[EventsNode, ActionsNode]] = Field(..., description="Events and actions to include") class PathsQuery(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - aggregation_group_type_index: Optional[float] = Field(default=None, description="Groups aggregation") - dateRange: Optional[DateRange] = Field(default=None, description="Date range for the query") + class Config: + extra = Extra.forbid + + aggregation_group_type_index: Optional[float] = Field(None, description="Groups aggregation") + dateRange: Optional[DateRange] = Field(None, description="Date range for the query") filterTestAccounts: Optional[bool] = Field( - default=None, description="Exclude internal and test users by applying the respective filters" + None, description="Exclude internal and test users by applying the respective filters" ) - kind: Literal["PathsQuery"] = "PathsQuery" - pathsFilter: Optional[PathsFilter] = Field(default=None, description="Properties specific to the paths insight") + kind: str = Field("PathsQuery", const=True) + pathsFilter: Optional[PathsFilter] = Field(None, description="Properties specific to the paths insight") properties: Optional[ Union[ List[ @@ -1222,19 +1213,17 @@ class PathsQuery(BaseModel): ], PropertyGroupFilter, ] - ] = Field(default=None, description="Property filters for all series") - samplingFactor: Optional[float] = Field(default=None, description="Sampling rate") + ] = Field(None, description="Property filters for all series") + samplingFactor: Optional[float] = Field(None, description="Sampling rate") class InsightVizNode(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - embedded: Optional[bool] = Field(default=None, description="Query is embedded inside another bordered component") - full: Optional[bool] = Field( - default=None, description="Show with most visual options enabled. Used in insight scene." - ) - kind: Literal["InsightVizNode"] = "InsightVizNode" + class Config: + extra = Extra.forbid + + embedded: Optional[bool] = Field(None, description="Query is embedded inside another bordered component") + full: Optional[bool] = Field(None, description="Show with most visual options enabled. Used in insight scene.") + kind: str = Field("InsightVizNode", const=True) showCorrelationTable: Optional[bool] = None showFilters: Optional[bool] = None showHeader: Optional[bool] = None @@ -1245,8 +1234,8 @@ class InsightVizNode(BaseModel): source: Union[TrendsQuery, FunnelsQuery, RetentionQuery, PathsQuery, StickinessQuery, LifecycleQuery] -class Model(RootModel): - root: Union[ +class Model(BaseModel): + __root__: Union[ DataTableNode, SavedInsightNode, InsightVizNode, @@ -1262,4 +1251,4 @@ class Model(RootModel): ] -PropertyGroupFilterValue.model_rebuild() +PropertyGroupFilterValue.update_forward_refs() diff --git a/requirements-dev.in b/requirements-dev.in index b21da42a9ee2e..8abc899cfbd14 100644 --- a/requirements-dev.in +++ b/requirements-dev.in @@ -15,7 +15,7 @@ ruff>=0.0.257 pip-tools==6.13.0 mypy==0.981 mypy-extensions==0.4.3 -datamodel-code-generator==0.21.5 +datamodel-code-generator==0.16.1 djangorestframework-stubs==1.4.0 django-stubs==1.8.0 Faker==17.5.0 diff --git a/requirements-dev.txt b/requirements-dev.txt index 2d93601fe05ee..8b0f3b0eb4875 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -4,10 +4,6 @@ # # pip-compile requirements-dev.in # -annotated-types==0.5.0 - # via - # -c requirements.txt - # pydantic argcomplete==2.0.0 # via datamodel-code-generator asgiref==3.3.2 @@ -66,7 +62,7 @@ cryptography==37.0.2 # -c requirements.txt # pyopenssl # urllib3 -datamodel-code-generator==0.21.5 +datamodel-code-generator==0.16.1 # via -r requirements-dev.in django==3.2.19 # via @@ -87,7 +83,7 @@ dnspython==2.2.1 # email-validator docopt==0.6.2 # via pytest-watch -email-validator==2.0.0.post2 +email-validator==1.3.1 # via pydantic exceptiongroup==1.1.2 # via pytest @@ -182,14 +178,10 @@ pycparser==2.20 # via # -c requirements.txt # cffi -pydantic[email]==2.3.0 +pydantic[email]==1.10.4 # via # -c requirements.txt # datamodel-code-generator -pydantic-core==2.6.3 - # via - # -c requirements.txt - # pydantic pyopenssl==22.0.0 # via # -c requirements.txt @@ -299,6 +291,8 @@ tomli==1.2.3 # mypy # pyproject-hooks # pytest +typed-ast==1.5.4 + # via datamodel-code-generator types-freezegun==1.1.10 # via -r requirements-dev.in types-markdown==3.3.9 @@ -315,7 +309,7 @@ types-redis==4.3.20 # via -r requirements-dev.in types-requests==2.26.1 # via -r requirements-dev.in -typing-extensions==4.7.1 +typing-extensions==4.4.0 # via # -c requirements.txt # django-stubs @@ -324,7 +318,6 @@ typing-extensions==4.7.1 # jsonschema-spec # mypy # pydantic - # pydantic-core uritemplate==4.1.1 # via # -c requirements.txt diff --git a/requirements.in b/requirements.in index 222e788c48182..09b47a4c2aa95 100644 --- a/requirements.in +++ b/requirements.in @@ -57,7 +57,7 @@ posthoganalytics==3.0.1 prance==0.22.2.22.0 psycopg2-binary==2.9.7 pyarrow==12.0.1 -pydantic==2.3.0 +pydantic==1.10.4 pyjwt==2.4.0 python-dateutil>=2.8.2 python3-saml==1.12.0 diff --git a/requirements.txt b/requirements.txt index 949d3fc8cc1ec..4fac42e90302a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,8 +15,6 @@ amqp==2.6.0 # via # -r requirements.in # kombu -annotated-types==0.5.0 - # via pydantic antlr4-python3-runtime==4.13.0 # via -r requirements.in asgiref==3.3.2 @@ -339,10 +337,8 @@ pycparser==2.20 # via cffi pycryptodomex==3.18.0 # via snowflake-connector-python -pydantic==2.3.0 +pydantic==1.10.4 # via -r requirements.in -pydantic-core==2.6.3 - # via pydantic pyjwt==2.4.0 # via # -r requirements.in @@ -484,10 +480,9 @@ types-protobuf==4.22.0.0 # via temporalio types-s3transfer==0.6.1 # via boto3-stubs -typing-extensions==4.7.1 +typing-extensions==4.4.0 # via # pydantic - # pydantic-core # qrcode # snowflake-connector-python # temporalio