From 213d219d3a2042ddf0b190288fab00826e642d85 Mon Sep 17 00:00:00 2001 From: Justin Smith Date: Fri, 28 Feb 2025 16:02:52 -0600 Subject: [PATCH] source-monday: Simplify and relax model definitions Modify GraphQL and models to be more flexible: - Update USERS GraphQL query to support pagination - Remove strict field definitions in models - Simplify model structures for Tag, Team, User, and Item - Adjust type hints and remove unnecessary validators --- source-monday/source_monday/graphql.py | 4 +- source-monday/source_monday/models.py | 166 ++---------------- .../snapshots/snapshots__capture__stdout.json | 10 +- 3 files changed, 17 insertions(+), 163 deletions(-) diff --git a/source-monday/source_monday/graphql.py b/source-monday/source_monday/graphql.py index 428fca7fa..744cbbaf5 100644 --- a/source-monday/source_monday/graphql.py +++ b/source-monday/source_monday/graphql.py @@ -341,8 +341,8 @@ async def fetch_items_by_boards( """ USERS = """ -query { - users { +query ($limit: Int = 10, $page: Int = 1) { + users(limit: $limit, page: $page) { birthday country_code created_at diff --git a/source-monday/source_monday/models.py b/source-monday/source_monday/models.py index 8d6808aaf..8b93700f2 100644 --- a/source-monday/source_monday/models.py +++ b/source-monday/source_monday/models.py @@ -86,10 +86,7 @@ class Advanced(BaseModel, extra="forbid"): ConnectorState = GenericConnectorState[ResourceState] - - ResponseObject = TypeVar("ResponseObject", bound=BaseModel) -State = Literal["active", "all", "archived", "deleted"] class FullRefreshResource(BaseDocument, extra="allow"): @@ -118,12 +115,8 @@ class GraphQLResponse(BaseModel, Generic[ResponseObject], extra="forbid"): errors: list[GraphQLError] | None = None -class ActivityLog(BaseModel, extra="forbid"): - id: str - entity: Literal["board", "pulse"] - event: str +class ActivityLog(BaseModel, extra="allow"): data: dict[str, Any] = Field(default_factory=dict) - created_at: AwareDatetime @field_validator("data", mode="before") @classmethod @@ -132,17 +125,8 @@ def parse_json_data(cls, v: Any) -> dict[str, Any]: return json.loads(v) return v - @field_validator("created_at", mode="before") - @classmethod - def parse_created_at(cls, v: Any) -> datetime: - if isinstance(v, str): - unix_millis = int(v) / 10_000 - return datetime.fromtimestamp(unix_millis / 1_000, tz=UTC) - raise ValueError(f"Invalid created_at value: {v}") - -class BoardActivityLogs(BaseModel, extra="forbid"): - id: str +class BoardActivityLogs(BaseModel, extra="allow"): activity_logs: list[ActivityLog] @@ -150,129 +134,26 @@ class ActivityLogsResponse(BaseModel, extra="forbid"): boards: list[BoardActivityLogs] -# A simple reference model for entities with just an id. -class EntityRef(BaseModel, extra="forbid"): - id: str - - -class Column(BaseModel, extra="forbid"): - archived: bool - description: str | None = None - id: str - settings_str: str | None = None - title: str - type: str - width: int | None = None - - -class Group(BaseModel, extra="forbid"): - archived: bool - color: str | None = None - deleted: bool - id: str - position: int | None = None - title: str - - -class Tag(BaseDocument, extra="forbid"): - id: str - color: str - name: str - - -class View(BaseModel, extra="forbid"): - id: str - name: str - settings_str: str | None = None - type: str - view_specific_data_str: str | None = None - - -class Workspace(BaseModel, extra="forbid"): - id: str - name: str - kind: str - description: str | None = None +class Tag(BaseDocument, extra="allow"): + pass -class Board(BaseDocument, extra="forbid"): - id: str - name: str - board_kind: str - type: str - columns: list[Column] - communication: str | None = None - description: str | None = None - groups: list[Group] - owners: list[EntityRef] - creator: EntityRef - permissions: str | None = None - state: str - subscribers: list[EntityRef] - tags: list[Tag] - top_group: EntityRef +class Board(BaseDocument, extra="allow"): updated_at: AwareDatetime - updates: list[EntityRef] - views: list[View] - workspace: Workspace class BoardsResponse(BaseModel, extra="forbid"): boards: list[Board] -class BoardRef(BaseModel, extra="forbid"): - id: str - name: str - - -class Asset(BaseModel, extra="forbid"): - created_at: AwareDatetime - file_extension: str - file_size: int - id: str - name: str - original_geometry: str | None = None - public_url: str - uploaded_by: EntityRef - url: str - url_thumbnail: str - - -class ColumnValue(BaseModel, extra="forbid"): - id: str - text: str | None = None - type: str - value: str | None = None - - -class GroupRef(BaseModel, extra="forbid"): - id: str - - class ParentItemRef(BaseModel, extra="forbid"): id: str -class Update(BaseModel, extra="forbid"): +class Item(BaseDocument, extra="allow"): id: str - - -class Item(BaseDocument, extra="forbid"): - id: str - name: str - assets: list[Asset] - board: BoardRef - column_values: list[ColumnValue] - created_at: AwareDatetime - creator_id: str - group: GroupRef parent_item: ParentItemRef | None = None - state: str - subscribers: list[EntityRef] updated_at: AwareDatetime - updates: list[Update] - subitems: list["Item"] | None = None class ItemsPage(BaseModel, extra="forbid"): @@ -297,44 +178,17 @@ class ItemsByIdResponse(BaseModel, extra="forbid"): items: list[Item] | None = Field(default_factory=list) -class Team(BaseDocument, extra="forbid"): - id: str - name: str - picture_url: str | None = None - users: list[EntityRef] - owners: list[EntityRef] +class Team(BaseDocument, extra="allow"): + pass class TeamsResponse(BaseModel, extra="forbid"): teams: list[Team] -class User(BaseDocument, extra="forbid"): - birthday: str | None = None - country_code: str | None = None - created_at: AwareDatetime | None = None - join_date: AwareDatetime | None = None - email: str | None = None - enabled: bool +class User(BaseDocument, extra="allow"): id: str - is_admin: bool - is_guest: bool - is_pending: bool - is_view_only: bool - is_verified: bool - location: str | None = None - mobile_phone: str | None = None - name: str - phone: str | None = None - photo_original: str | None = None - photo_small: str | None = None - photo_thumb: str | None = None - photo_thumb_small: str | None = None - photo_tiny: str | None = None - time_zone_identifier: str | None = None - title: str | None = None - url: str | None = None - utc_hours_diff: float | None = None + pass class UsersResponse(BaseModel, extra="forbid"): diff --git a/source-monday/tests/snapshots/snapshots__capture__stdout.json b/source-monday/tests/snapshots/snapshots__capture__stdout.json index 79ea77675..7dda0264d 100644 --- a/source-monday/tests/snapshots/snapshots__capture__stdout.json +++ b/source-monday/tests/snapshots/snapshots__capture__stdout.json @@ -54,7 +54,7 @@ "time_zone_identifier": "America/Chicago", "title": null, "url": "https://estuarydev.monday.com/users/71985416", - "utc_hours_diff": -6.0 + "utc_hours_diff": -6 } ], [ @@ -144,7 +144,7 @@ "color": "#579bfc", "deleted": false, "id": "new_group29179", - "position": 65472, + "position": "65472.0", "title": "To-Do" }, { @@ -152,7 +152,7 @@ "color": "#00c875", "deleted": false, "id": "new_group43041", - "position": 98208, + "position": "98208", "title": "Completed" } ], @@ -175,7 +175,7 @@ "id": "new_group29179" }, "type": "board", - "updated_at": "2025-02-24T17:14:41Z", + "updated_at": "2025-02-28T21:54:49Z", "updates": [], "views": [], "workspace": { @@ -242,7 +242,7 @@ "color": "#579bfc", "deleted": false, "id": "topics", - "position": 65536, + "position": "65536", "title": "Subitems" } ],