From 26f29f11e4400d1072b03033ca909b0c7c938520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Oberm=C3=BCller?= Date: Mon, 18 Sep 2023 15:05:46 +0200 Subject: [PATCH] chore(python): upgrade pydantic and datamodel-code-generator (#17477) --- package.json | 2 +- posthog/api/insight.py | 2 +- posthog/api/query.py | 8 +- posthog/api/test/test_query.py | 7 +- posthog/hogql/constants.py | 5 +- posthog/hogql/database/database.py | 11 +- posthog/hogql/database/models.py | 21 +- posthog/hogql/database/schema/numbers.py | 8 +- posthog/hogql/test/test_metadata.py | 6 +- posthog/hogql/test/test_query.py | 2 +- .../hogql_queries/lifecycle_query_runner.py | 2 +- posthog/schema.py | 649 +++++++++--------- requirements-dev.in | 2 +- requirements-dev.txt | 19 +- requirements.in | 2 +- requirements.txt | 9 +- 16 files changed, 385 insertions(+), 370 deletions(-) diff --git a/package.json b/package.json index d57d8824da145..be3be7cd6ae02 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-subclass-enum --input frontend/src/queries/schema.json --input-file-type jsonschema --output posthog/schema.py && black posthog/schema.py", + "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", "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/posthog/api/insight.py b/posthog/api/insight.py index 28713fd083f5e..8fc0dfa282735 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.parse_obj(query) + schema.Model.model_validate(query) except Exception as error: raise ParseError(detail=str(error)) else: diff --git a/posthog/api/query.py b/posthog/api/query.py index 385f14d2f7905..c3cbb48cc9529 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.parse_obj(data) + schema.Model.model_validate(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.parse_obj(query_json) + events_query = EventsQuery.model_validate(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.parse_obj(query_json) + hogql_query = HogQLQuery.model_validate(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.parse_obj(query_json) + metadata_query = HogQLMetadata.model_validate(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 4e046a9268059..cde8de9c22196 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.parse_obj(api_response) + query.response = HogQLQueryResponse.model_validate(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=value_error.const; given=Tomato Soup" in api_response.json()["detail"] + assert "type=literal_error, input_value='Tomato Soup'" in api_response.json()["detail"] @snapshot_clickhouse_queries def test_full_hogql_query_view(self): @@ -498,7 +498,6 @@ 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/", { @@ -511,7 +510,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.parse_obj(api_response) + query.response = HogQLQueryResponse.model_validate(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 a5c7d35f13675..fc01500f79e83 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 BaseModel, Extra +from pydantic import ConfigDict, BaseModel ConstantDataType: TypeAlias = Literal[ "int", "float", "str", "bool", "array", "tuple", "date", "datetime", "uuid", "unknown" @@ -24,8 +24,7 @@ # Settings applied on top of all HogQL queries. class HogQLSettings(BaseModel): - class Config: - extra = Extra.forbid + model_config = ConfigDict(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 4f5cea81d1425..5cddd747c3429 100644 --- a/posthog/hogql/database/database.py +++ b/posthog/hogql/database/database.py @@ -1,6 +1,6 @@ -from typing import Any, Dict, List, Literal, Optional, TypedDict +from typing import Any, ClassVar, Dict, List, Literal, Optional, TypedDict from zoneinfo import ZoneInfo, ZoneInfoNotFoundError -from pydantic import BaseModel, Extra +from pydantic import ConfigDict, BaseModel from posthog.hogql.database.models import ( FieldTraverser, @@ -33,8 +33,7 @@ class Database(BaseModel): - class Config: - extra = Extra.allow + model_config = ConfigDict(extra="allow") # Users can query from the tables below events: EventsTable = EventsTable() @@ -58,7 +57,7 @@ class Config: numbers: NumbersTable = NumbersTable() # clunky: keep table names in sync with above - _table_names: List[str] = [ + _table_names: ClassVar[List[str]] = [ "events", "groups", "person", @@ -182,7 +181,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.__fields__.keys(): + for table_key in database.model_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 dc5b74724b96f..e5283eb68142e 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 BaseModel, Extra +from pydantic import ConfigDict, BaseModel from posthog.hogql.errors import HogQLException, NotImplementedException @@ -16,8 +16,7 @@ class DatabaseField(FieldOrTable): Base class for a field in a database table. """ - class Config: - extra = Extra.forbid + model_config = ConfigDict(extra="forbid") name: str array: Optional[bool] = None @@ -57,17 +56,14 @@ class BooleanDatabaseField(DatabaseField): class FieldTraverser(FieldOrTable): - class Config: - extra = Extra.forbid + model_config = ConfigDict(extra="forbid") chain: List[str] class Table(FieldOrTable): fields: Dict[str, FieldOrTable] - - class Config: - extra = Extra.forbid + model_config = ConfigDict(extra="forbid") def has_field(self, name: str) -> bool: return name in self.fields @@ -102,8 +98,7 @@ def get_asterisk(self): class LazyJoin(FieldOrTable): - class Config: - extra = Extra.forbid + model_config = ConfigDict(extra="forbid") join_function: Callable[[str, str, Dict[str, Any]], Any] join_table: Table @@ -115,8 +110,7 @@ class LazyTable(Table): A table that is replaced with a subquery returned from `lazy_select(requested_fields: Dict[name, chain])` """ - class Config: - extra = Extra.forbid + model_config = ConfigDict(extra="forbid") def lazy_select(self, requested_fields: Dict[str, List[str]]) -> Any: raise NotImplementedException("LazyTable.lazy_select not overridden") @@ -127,8 +121,7 @@ class VirtualTable(Table): A nested table that reuses the parent for storage. E.g. events.person.* fields with PoE enabled. """ - class Config: - extra = Extra.forbid + model_config = ConfigDict(extra="forbid") class FunctionCallTable(Table): diff --git a/posthog/hogql/database/schema/numbers.py b/posthog/hogql/database/schema/numbers.py index 6db50440cda9e..01c09ac66d797 100644 --- a/posthog/hogql/database/schema/numbers.py +++ b/posthog/hogql/database/schema/numbers.py @@ -1,4 +1,4 @@ -from typing import Dict +from typing import Dict, Optional from posthog.hogql.database.models import ( IntegerDatabaseField, @@ -14,9 +14,9 @@ class NumbersTable(FunctionCallTable): fields: Dict[str, FieldOrTable] = NUMBERS_TABLE_FIELDS - name = "numbers" - min_args = 1 - max_args = 2 + name: str = "numbers" + min_args: Optional[int] = 1 + max_args: Optional[int] = 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 584dbfab67d0d..54dbcb17a9eb6 100644 --- a/posthog/hogql/test/test_metadata.py +++ b/posthog/hogql/test/test_metadata.py @@ -8,10 +8,12 @@ class TestMetadata(ClickhouseTestMixin, APIBaseTest): maxDiff = None def _expr(self, query: str) -> HogQLMetadataResponse: - return get_hogql_metadata(query=HogQLMetadata(expr=query), team=self.team) + return get_hogql_metadata(query=HogQLMetadata(kind="HogQLMetadata", expr=query, response=None), team=self.team) def _select(self, query: str) -> HogQLMetadataResponse: - return get_hogql_metadata(query=HogQLMetadata(select=query), team=self.team) + return get_hogql_metadata( + query=HogQLMetadata(kind="HogQLMetadata", select=query, response=None), 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 cb7d19f9df337..d45a1edcb9672 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 2b970bb95156c..ea43b3cd69aa0 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.parse_obj(query) + self.query = LifecycleQuery.model_validate(query) def to_query(self) -> ast.SelectQuery: placeholders = { diff --git a/posthog/schema.py b/posthog/schema.py index b988b9618e0ef..a1da2403d0d8f 100644 --- a/posthog/schema.py +++ b/posthog/schema.py @@ -6,7 +6,8 @@ from enum import Enum from typing import Any, Dict, List, Optional, Union -from pydantic import BaseModel, Extra, Field +from pydantic import BaseModel, ConfigDict, Field, RootModel +from typing_extensions import Literal class MathGroupTypeIndex(float, Enum): @@ -62,12 +63,12 @@ class ChartDisplayType(str, Enum): class CohortPropertyFilter(BaseModel): - class Config: - extra = Extra.forbid - - key: str = Field("id", const=True) + model_config = ConfigDict( + extra="forbid", + ) + key: Literal["id"] = "id" label: Optional[str] = None - type: str = Field("cohort", const=True) + type: Literal["cohort"] = "cohort" value: float @@ -82,9 +83,9 @@ class CountPerActorMathType(str, Enum): class DatabaseSchemaQueryResponseField(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) chain: Optional[List[str]] = None fields: Optional[List[str]] = None key: str @@ -93,9 +94,9 @@ class Config: class DateRange(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) date_from: Optional[str] = None date_to: Optional[str] = None @@ -108,9 +109,9 @@ class Key(str, Enum): class ElementType(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) attr_class: Optional[List[str]] = None attr_id: Optional[str] = None attributes: Dict[str, str] @@ -123,9 +124,9 @@ class Config: class EmptyPropertyFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) key: Optional[Any] = None operator: Optional[Any] = None type: Optional[Any] = None @@ -139,18 +140,18 @@ class EntityType(str, Enum): class Person(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) distinct_ids: List[str] is_identified: Optional[bool] = None properties: Dict[str, Any] class EventType(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) distinct_id: str elements: List[ElementType] elements_chain: Optional[str] = None @@ -162,18 +163,10 @@ class Config: 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): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) next: Optional[str] = None results: List[EventType] @@ -204,9 +197,9 @@ class FunnelPathType(str, Enum): class FunnelStepRangeEntityFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) custom_name: Optional[str] = None funnel_from_step: Optional[float] = None funnel_to_step: Optional[float] = None @@ -234,9 +227,9 @@ class FunnelCorrelationPersonConverted(str, Enum): class HogQLNotice(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) end: Optional[float] = None fix: Optional[str] = None message: str @@ -258,9 +251,9 @@ class LifecycleToggle(str, Enum): class PathCleaningFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) alias: Optional[str] = None regex: Optional[str] = None @@ -273,9 +266,9 @@ class PathType(str, Enum): class PathsFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) edge_limit: Optional[float] = None end_point: Optional[str] = None exclude_events: Optional[List[str]] = None @@ -330,21 +323,21 @@ class PropertyOperator(str, Enum): class QueryTiming(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + 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): - class Config: - extra = Extra.forbid - - key: str = Field("duration", const=True) + model_config = ConfigDict( + extra="forbid", + ) + key: Literal["duration"] = "duration" label: Optional[str] = None operator: PropertyOperator - type: str = Field("recording", const=True) + type: Literal["recording"] = "recording" value: float @@ -366,58 +359,62 @@ class RetentionType(str, Enum): class SavedInsightNode(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) allowSorting: Optional[bool] = Field( - None, description="Can the user click on column headers to sort the table? (default: true)" + 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." ) - 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)") + kind: Literal["SavedInsightNode"] = "SavedInsightNode" + propertiesViaUrl: Optional[bool] = Field(default=None, description="Link properties via the URL (default: false)") shortId: str - showActions: Optional[bool] = Field(None, description="Show the kebab menu at the end of the row") + showActions: Optional[bool] = Field(default=None, description="Show the kebab menu at the end of the row") showColumnConfigurator: Optional[bool] = Field( - None, description="Show a button to configure the table's columns if possible" + default=None, description="Show a button to configure the table's columns if possible" ) showCorrelationTable: Optional[bool] = None - 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") + 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") showEventFilter: Optional[bool] = Field( - None, description="Include an event filter above the table (EventsNode only)" + default=None, description="Include an event filter above the table (EventsNode only)" ) - showExport: Optional[bool] = Field(None, description="Show the export button") + showExport: Optional[bool] = Field(default=None, description="Show the export button") showFilters: Optional[bool] = None showHeader: Optional[bool] = None - showHogQLEditor: Optional[bool] = Field(None, description="Include a HogQL query editor above HogQL tables") + showHogQLEditor: Optional[bool] = Field(default=None, description="Include a HogQL query editor above HogQL tables") showLastComputation: Optional[bool] = None showLastComputationRefresh: Optional[bool] = None showOpenEditorButton: Optional[bool] = Field( - None, description="Show a button to open the current query as a new insight. (default: true)" + default=None, description="Show a button to open the current query as a new insight. (default: true)" ) showPersistentColumnConfigurator: Optional[bool] = Field( - None, description="Show a button to configure and persist the table's default columns if possible" + default=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") + 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") showResults: Optional[bool] = None - 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)") + 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)") showTable: Optional[bool] = None - showTimings: Optional[bool] = Field(None, description="Show a detailed query timing breakdown") + showTimings: Optional[bool] = Field(default=None, description="Show a detailed query timing breakdown") class SessionPropertyFilter(BaseModel): - class Config: - extra = Extra.forbid - - key: str = Field("$session_duration", const=True) + model_config = ConfigDict( + extra="forbid", + ) + key: Literal["$session_duration"] = "$session_duration" label: Optional[str] = None operator: PropertyOperator - type: str = Field("session", const=True) + type: Literal["session"] = "session" value: Optional[Union[str, float, List[Union[str, float]]]] = None @@ -434,9 +431,9 @@ class StepOrderValue(str, Enum): class StickinessFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) compare: Optional[bool] = None display: Optional[ChartDisplayType] = None hidden_legend_indexes: Optional[List[float]] = None @@ -447,16 +444,16 @@ class Config: class TimeToSeeDataSessionsQueryResponse(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) results: List[Dict[str, Any]] class TrendsFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) aggregation_axis_format: Optional[AggregationAxisFormat] = None aggregation_axis_postfix: Optional[str] = None aggregation_axis_prefix: Optional[str] = None @@ -473,18 +470,18 @@ class Config: class Breakdown(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) normalize_url: Optional[bool] = None property: Union[str, float] type: BreakdownType class BreakdownFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + 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 @@ -494,31 +491,31 @@ class Config: class ElementPropertyFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) key: Key label: Optional[str] = None operator: PropertyOperator - type: str = Field("element", const=True) + type: Literal["element"] = "element" value: Optional[Union[str, float, List[Union[str, float]]]] = None class EventPropertyFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) key: str label: Optional[str] = None operator: PropertyOperator - type: str = Field("event", const=True, description="Event properties") + type: Literal["event"] = Field(default="event", description="Event properties") value: Optional[Union[str, float, List[Union[str, float]]]] = None class EventsQueryResponse(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) columns: List hasMore: Optional[bool] = None results: List[List] @@ -527,20 +524,20 @@ class Config: class FeaturePropertyFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) key: str label: Optional[str] = None operator: PropertyOperator - type: str = Field("feature", const=True, description='Event property with "$feature/" prepended') + type: Literal["feature"] = Field(default="feature", description='Event property with "$feature/" prepended') value: Optional[Union[str, float, List[Union[str, float]]]] = None class FunnelsFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) bin_count: Optional[Union[float, str]] = None breakdown_attribution_type: Optional[BreakdownAttributionType] = None breakdown_attribution_value: Optional[float] = None @@ -566,21 +563,21 @@ class Config: class GroupPropertyFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) group_type_index: Optional[float] = None key: str label: Optional[str] = None operator: PropertyOperator - type: str = Field("group", const=True) + type: Literal["group"] = "group" value: Optional[Union[str, float, List[Union[str, float]]]] = None class HogQLMetadataResponse(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) errors: List[HogQLNotice] inputExpr: Optional[str] = None inputSelect: Optional[str] = None @@ -591,19 +588,19 @@ class Config: class HogQLPropertyFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) key: str label: Optional[str] = None - type: str = Field("hogql", const=True) + type: Literal["hogql"] = "hogql" value: Optional[Union[str, float, List[Union[str, float]]]] = None class HogQLQueryResponse(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) clickhouse: Optional[str] = None columns: Optional[List] = None hogql: Optional[str] = None @@ -614,37 +611,37 @@ class Config: class LifecycleFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) show_values_on_series: Optional[bool] = None shown_as: Optional[ShownAsValue] = None toggledLifecycles: Optional[List[LifecycleToggle]] = None class LifecycleQueryResponse(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) result: List[Dict[str, Any]] timings: Optional[List[QueryTiming]] = None class PersonPropertyFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) key: str label: Optional[str] = None operator: PropertyOperator - type: str = Field("person", const=True, description="Person properties") + type: Literal["person"] = Field(default="person", description="Person properties") value: Optional[Union[str, float, List[Union[str, float]]]] = None class RetentionFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) period: Optional[RetentionPeriod] = None retention_reference: Optional[RetentionReference] = None retention_type: Optional[RetentionType] = None @@ -654,31 +651,31 @@ class Config: class TimeToSeeDataSessionsQuery(BaseModel): - 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") + 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 DatabaseSchemaQuery(BaseModel): - class Config: - extra = Extra.forbid - - kind: str = Field("DatabaseSchemaQuery", const=True) + model_config = ConfigDict( + extra="forbid", + ) + kind: Literal["DatabaseSchemaQuery"] = "DatabaseSchemaQuery" response: Optional[Dict[str, List[DatabaseSchemaQueryResponseField]]] = Field( - None, description="Cached query response" + default=None, description="Cached query response" ) class EventsNode(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) custom_name: Optional[str] = None - event: Optional[str] = Field(None, description="The event or `null` for all events.") + event: Optional[str] = Field(default=None, description="The event or `null` for all events.") fixedProperties: Optional[ List[ Union[ @@ -695,17 +692,19 @@ class Config: ] ] ] = Field( - None, + default=None, description="Fixed properties in the query, can't be edited in the interface (e.g. scoping down by person)", ) - kind: str = Field("EventsNode", const=True) + kind: Literal["EventsNode"] = "EventsNode" limit: Optional[float] = None - math: Optional[Union[BaseMathType, PropertyMathType, CountPerActorMathType, str, str]] = None - math_group_type_index: Optional[MathGroupTypeIndex1] = None + math: Optional[ + Union[BaseMathType, PropertyMathType, CountPerActorMathType, Literal["unique_group"], Literal["hogql"]] + ] = None + math_group_type_index: Optional[MathGroupTypeIndex] = None math_hogql: Optional[str] = None math_property: Optional[str] = None name: Optional[str] = None - orderBy: Optional[List[str]] = Field(None, description="Columns to order by") + orderBy: Optional[List[str]] = Field(default=None, description="Columns to order by") properties: Optional[ List[ Union[ @@ -721,18 +720,18 @@ class Config: EmptyPropertyFilter, ] ] - ] = Field(None, description="Properties configurable in the interface") - response: Optional[Response] = Field(None, description="Return a limited set of data") + ] = Field(default=None, description="Properties configurable in the interface") + response: Optional[Response] = Field(default=None, description="Return a limited set of data") class EventsQuery(BaseModel): - 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") + 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") fixedProperties: Optional[ List[ Union[ @@ -749,14 +748,14 @@ class Config: ] ] ] = Field( - None, + default=None, description="Fixed properties in the query, can't be edited in the interface (e.g. scoping down by 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") + 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") properties: Optional[ List[ Union[ @@ -772,16 +771,16 @@ class Config: EmptyPropertyFilter, ] ] - ] = Field(None, description="Properties configurable in the interface") - response: Optional[EventsQueryResponse] = Field(None, description="Cached query response") + ] = Field(default=None, description="Properties configurable in the interface") + response: Optional[EventsQueryResponse] = Field(default=None, description="Cached query response") select: List[str] = Field(..., description="Return a limited set of data. Required.") - where: Optional[List[str]] = Field(None, description="HogQL filters to apply on returned data") + where: Optional[List[str]] = Field(default=None, description="HogQL filters to apply on returned data") class HogQLFilters(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) dateRange: Optional[DateRange] = None properties: Optional[ List[ @@ -802,30 +801,30 @@ class Config: class HogQLMetadata(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) expr: Optional[str] = None filters: Optional[HogQLFilters] = None - kind: str = Field("HogQLMetadata", const=True) - response: Optional[HogQLMetadataResponse] = Field(None, description="Cached query response") + kind: Literal["HogQLMetadata"] = "HogQLMetadata" + response: Optional[HogQLMetadataResponse] = Field(default=None, description="Cached query response") select: Optional[str] = None class HogQLQuery(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) filters: Optional[HogQLFilters] = None - kind: str = Field("HogQLQuery", const=True) + kind: Literal["HogQLQuery"] = "HogQLQuery" query: str - response: Optional[HogQLQueryResponse] = Field(None, description="Cached query response") + response: Optional[HogQLQueryResponse] = Field(default=None, description="Cached query response") class PersonsNode(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) cohort: Optional[float] = None distinctId: Optional[str] = None fixedProperties: Optional[ @@ -844,10 +843,10 @@ class Config: ] ] ] = Field( - None, + default=None, description="Fixed properties in the query, can't be edited in the interface (e.g. scoping down by person)", ) - kind: str = Field("PersonsNode", const=True) + kind: Literal["PersonsNode"] = "PersonsNode" limit: Optional[float] = None offset: Optional[float] = None properties: Optional[ @@ -865,15 +864,15 @@ class Config: EmptyPropertyFilter, ] ] - ] = Field(None, description="Properties configurable in the interface") - response: Optional[Dict[str, Any]] = Field(None, description="Cached query response") + ] = Field(default=None, description="Properties configurable in the interface") + response: Optional[Dict[str, Any]] = Field(default=None, description="Cached query response") search: Optional[str] = None class PropertyGroupFilterValue(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) type: FilterLogicalOperator values: List[ Union[ @@ -895,9 +894,9 @@ class Config: class ActionsNode(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) custom_name: Optional[str] = None fixedProperties: Optional[ List[ @@ -915,12 +914,14 @@ class Config: ] ] ] = Field( - None, + default=None, description="Fixed properties in the query, can't be edited in the interface (e.g. scoping down by person)", ) id: float - kind: str = Field("ActionsNode", const=True) - math: Optional[Union[BaseMathType, PropertyMathType, CountPerActorMathType, str, str]] = None + kind: Literal["ActionsNode"] = "ActionsNode" + math: Optional[ + Union[BaseMathType, PropertyMathType, CountPerActorMathType, Literal["unique_group"], Literal["hogql"]] + ] = None math_group_type_index: Optional[MathGroupTypeIndex] = None math_hogql: Optional[str] = None math_property: Optional[str] = None @@ -940,74 +941,76 @@ class Config: EmptyPropertyFilter, ] ] - ] = Field(None, description="Properties configurable in the interface") - response: Optional[Dict[str, Any]] = Field(None, description="Cached query response") + ] = Field(default=None, description="Properties configurable in the interface") + response: Optional[Dict[str, Any]] = Field(default=None, description="Cached query response") class DataTableNode(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) allowSorting: Optional[bool] = Field( - None, description="Can the user click on column headers to sort the table? (default: true)" + default=None, description="Can the user click on column headers to sort the table? (default: true)" ) columns: Optional[List[str]] = Field( - None, description="Columns shown in the table, unless the `source` provides them." + 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)" ) - 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.") + full: Optional[bool] = Field(default=None, description="Show with most visual options enabled. Used in scenes.") hiddenColumns: Optional[List[str]] = Field( - None, description="Columns that aren't shown in the table, even if in columns or returned data" + default=None, description="Columns that aren't shown in the table, even if in columns or returned data" ) - 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") + 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") showColumnConfigurator: Optional[bool] = Field( - None, description="Show a button to configure the table's columns if possible" + default=None, description="Show a button to configure the table's columns if possible" ) - 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") + 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") showEventFilter: Optional[bool] = Field( - None, description="Include an event filter above the table (EventsNode only)" + default=None, description="Include an event filter above the table (EventsNode only)" ) - showExport: Optional[bool] = Field(None, description="Show the export button") - showHogQLEditor: Optional[bool] = Field(None, description="Include a HogQL query editor above HogQL tables") + 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") showOpenEditorButton: Optional[bool] = Field( - None, description="Show a button to open the current query as a new insight. (default: true)" + default=None, description="Show a button to open the current query as a new insight. (default: true)" ) showPersistentColumnConfigurator: Optional[bool] = Field( - 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") + 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") source: Union[EventsNode, EventsQuery, PersonsNode, HogQLQuery, TimeToSeeDataSessionsQuery] = Field( ..., description="Source of the events" ) class PropertyGroupFilter(BaseModel): - class Config: - extra = Extra.forbid - + model_config = ConfigDict( + extra="forbid", + ) type: FilterLogicalOperator values: List[PropertyGroupFilterValue] class RetentionQuery(BaseModel): - 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") + 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") filterTestAccounts: Optional[bool] = Field( - None, description="Exclude internal and test users by applying the respective filters" + default=None, description="Exclude internal and test users by applying the respective filters" ) - kind: str = Field("RetentionQuery", const=True) + kind: Literal["RetentionQuery"] = "RetentionQuery" properties: Optional[ Union[ List[ @@ -1026,24 +1029,26 @@ class Config: ], PropertyGroupFilter, ] - ] = 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") + ] = 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") class StickinessQuery(BaseModel): - 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") + 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") filterTestAccounts: Optional[bool] = Field( - None, description="Exclude internal and test users by applying the respective filters" + default=None, description="Exclude internal and test users by applying the respective filters" ) interval: Optional[IntervalType] = Field( - None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" + default=None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" ) - kind: str = Field("StickinessQuery", const=True) + kind: Literal["StickinessQuery"] = "StickinessQuery" properties: Optional[ Union[ List[ @@ -1062,28 +1067,28 @@ class Config: ], PropertyGroupFilter, ] - ] = Field(None, description="Property filters for all series") - samplingFactor: Optional[float] = Field(None, description="Sampling rate") + ] = Field(default=None, description="Property filters for all series") + samplingFactor: Optional[float] = Field(default=None, description="Sampling rate") series: List[Union[EventsNode, ActionsNode]] = Field(..., description="Events and actions to include") stickinessFilter: Optional[StickinessFilter] = Field( - None, description="Properties specific to the stickiness insight" + default=None, description="Properties specific to the stickiness insight" ) class TrendsQuery(BaseModel): - 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") + 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") filterTestAccounts: Optional[bool] = Field( - None, description="Exclude internal and test users by applying the respective filters" + default=None, description="Exclude internal and test users by applying the respective filters" ) interval: Optional[IntervalType] = Field( - None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" + default=None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" ) - kind: str = Field("TrendsQuery", const=True) + kind: Literal["TrendsQuery"] = "TrendsQuery" properties: Optional[ Union[ List[ @@ -1102,27 +1107,29 @@ class Config: ], PropertyGroupFilter, ] - ] = Field(None, description="Property filters for all series") - samplingFactor: Optional[float] = Field(None, description="Sampling rate") + ] = Field(default=None, description="Property filters for all series") + samplingFactor: Optional[float] = Field(default=None, description="Sampling rate") series: List[Union[EventsNode, ActionsNode]] = Field(..., description="Events and actions to include") - trendsFilter: Optional[TrendsFilter] = Field(None, description="Properties specific to the trends insight") + trendsFilter: Optional[TrendsFilter] = Field(default=None, description="Properties specific to the trends insight") class FunnelsQuery(BaseModel): - 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") + 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") filterTestAccounts: Optional[bool] = Field( - None, description="Exclude internal and test users by applying the respective filters" + 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" ) - funnelsFilter: Optional[FunnelsFilter] = Field(None, description="Properties specific to the funnels insight") interval: Optional[IntervalType] = Field( - None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" + default=None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" ) - kind: str = Field("FunnelsQuery", const=True) + kind: Literal["FunnelsQuery"] = "FunnelsQuery" properties: Optional[ Union[ List[ @@ -1141,25 +1148,27 @@ class Config: ], PropertyGroupFilter, ] - ] = Field(None, description="Property filters for all series") - samplingFactor: Optional[float] = Field(None, description="Sampling rate") + ] = Field(default=None, description="Property filters for all series") + samplingFactor: Optional[float] = Field(default=None, description="Sampling rate") series: List[Union[EventsNode, ActionsNode]] = Field(..., description="Events and actions to include") class LifecycleQuery(BaseModel): - 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") + 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") filterTestAccounts: Optional[bool] = Field( - None, description="Exclude internal and test users by applying the respective filters" + default=None, description="Exclude internal and test users by applying the respective filters" ) interval: Optional[IntervalType] = Field( - None, description="Granularity of the response. Can be one of `hour`, `day`, `week` or `month`" + 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" ) - kind: str = Field("LifecycleQuery", const=True) - lifecycleFilter: Optional[LifecycleFilter] = Field(None, description="Properties specific to the lifecycle insight") properties: Optional[ Union[ List[ @@ -1178,23 +1187,23 @@ class Config: ], PropertyGroupFilter, ] - ] = Field(None, description="Property filters for all series") + ] = Field(default=None, description="Property filters for all series") response: Optional[LifecycleQueryResponse] = None - samplingFactor: Optional[float] = Field(None, description="Sampling rate") + samplingFactor: Optional[float] = Field(default=None, description="Sampling rate") series: List[Union[EventsNode, ActionsNode]] = Field(..., description="Events and actions to include") class PathsQuery(BaseModel): - 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") + 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") filterTestAccounts: Optional[bool] = Field( - None, description="Exclude internal and test users by applying the respective filters" + default=None, description="Exclude internal and test users by applying the respective filters" ) - kind: str = Field("PathsQuery", const=True) - pathsFilter: Optional[PathsFilter] = Field(None, description="Properties specific to the paths insight") + kind: Literal["PathsQuery"] = "PathsQuery" + pathsFilter: Optional[PathsFilter] = Field(default=None, description="Properties specific to the paths insight") properties: Optional[ Union[ List[ @@ -1213,17 +1222,19 @@ class Config: ], PropertyGroupFilter, ] - ] = Field(None, description="Property filters for all series") - samplingFactor: Optional[float] = Field(None, description="Sampling rate") + ] = Field(default=None, description="Property filters for all series") + samplingFactor: Optional[float] = Field(default=None, description="Sampling rate") class InsightVizNode(BaseModel): - 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) + 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" showCorrelationTable: Optional[bool] = None showFilters: Optional[bool] = None showHeader: Optional[bool] = None @@ -1234,8 +1245,8 @@ class Config: source: Union[TrendsQuery, FunnelsQuery, RetentionQuery, PathsQuery, StickinessQuery, LifecycleQuery] -class Model(BaseModel): - __root__: Union[ +class Model(RootModel): + root: Union[ DataTableNode, SavedInsightNode, InsightVizNode, @@ -1251,4 +1262,4 @@ class Model(BaseModel): ] -PropertyGroupFilterValue.update_forward_refs() +PropertyGroupFilterValue.model_rebuild() diff --git a/requirements-dev.in b/requirements-dev.in index 8abc899cfbd14..b21da42a9ee2e 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.16.1 +datamodel-code-generator==0.21.5 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 8b0f3b0eb4875..2d93601fe05ee 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -4,6 +4,10 @@ # # 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 @@ -62,7 +66,7 @@ cryptography==37.0.2 # -c requirements.txt # pyopenssl # urllib3 -datamodel-code-generator==0.16.1 +datamodel-code-generator==0.21.5 # via -r requirements-dev.in django==3.2.19 # via @@ -83,7 +87,7 @@ dnspython==2.2.1 # email-validator docopt==0.6.2 # via pytest-watch -email-validator==1.3.1 +email-validator==2.0.0.post2 # via pydantic exceptiongroup==1.1.2 # via pytest @@ -178,10 +182,14 @@ pycparser==2.20 # via # -c requirements.txt # cffi -pydantic[email]==1.10.4 +pydantic[email]==2.3.0 # 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 @@ -291,8 +299,6 @@ 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 @@ -309,7 +315,7 @@ types-redis==4.3.20 # via -r requirements-dev.in types-requests==2.26.1 # via -r requirements-dev.in -typing-extensions==4.4.0 +typing-extensions==4.7.1 # via # -c requirements.txt # django-stubs @@ -318,6 +324,7 @@ typing-extensions==4.4.0 # jsonschema-spec # mypy # pydantic + # pydantic-core uritemplate==4.1.1 # via # -c requirements.txt diff --git a/requirements.in b/requirements.in index 09b47a4c2aa95..222e788c48182 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==1.10.4 +pydantic==2.3.0 pyjwt==2.4.0 python-dateutil>=2.8.2 python3-saml==1.12.0 diff --git a/requirements.txt b/requirements.txt index 4fac42e90302a..949d3fc8cc1ec 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,6 +15,8 @@ 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 @@ -337,8 +339,10 @@ pycparser==2.20 # via cffi pycryptodomex==3.18.0 # via snowflake-connector-python -pydantic==1.10.4 +pydantic==2.3.0 # via -r requirements.in +pydantic-core==2.6.3 + # via pydantic pyjwt==2.4.0 # via # -r requirements.in @@ -480,9 +484,10 @@ types-protobuf==4.22.0.0 # via temporalio types-s3transfer==0.6.1 # via boto3-stubs -typing-extensions==4.4.0 +typing-extensions==4.7.1 # via # pydantic + # pydantic-core # qrcode # snowflake-connector-python # temporalio