smartsheet-python-sdk 3.9.0__tar.gz → 4.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- smartsheet_python_sdk-4.0.0/.claude/skills/implement-api-endpoint/SKILL.md +377 -0
- smartsheet_python_sdk-4.0.0/.claude/skills/review-api-endpoint/SKILL.md +559 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/.github/workflows/publish-distribution.yaml +6 -5
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/.github/workflows/publish-documentation.yaml +5 -5
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/.github/workflows/test-build.yaml +17 -20
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/.gitignore +10 -0
- smartsheet_python_sdk-4.0.0/ADVANCED.md +396 -0
- smartsheet_python_sdk-4.0.0/AGENTS.md +288 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/CHANGELOG.md +31 -1
- smartsheet_python_sdk-4.0.0/CLAUDE.md +3 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/CONTRIBUTING.md +84 -10
- {smartsheet_python_sdk-3.9.0/smartsheet_python_sdk.egg-info → smartsheet_python_sdk-4.0.0}/PKG-INFO +24 -26
- smartsheet_python_sdk-4.0.0/TESTING.md +114 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/pyproject.toml +8 -6
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/folders.py +1 -61
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/__init__.py +0 -1
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/create_report_result.py +1 -1
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/event.py +9 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report_destination.py +1 -1
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report_scope_inclusion.py +1 -1
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/sheet.py +0 -34
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/reports.py +0 -134
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/sheets.py +1 -155
- smartsheet_python_sdk-4.0.0/smartsheet/sights.py +236 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/smartsheet.py +0 -2
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/types.py +5 -1
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/util.py +5 -1
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/version.py +3 -3
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/webhooks.py +12 -9
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/workspaces.py +11 -251
- smartsheet_python_sdk-4.0.0/tests/mock_api/events/__init__.py +0 -0
- smartsheet_python_sdk-4.0.0/tests/mock_api/events/common_test_constants.py +38 -0
- smartsheet_python_sdk-4.0.0/tests/mock_api/events/test_list_events.py +233 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/reports/common_test_constants.py +0 -1
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/reports/test_add_report_columns.py +70 -70
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/reports/test_add_report_scope.py +19 -28
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/reports/test_create_report.py +221 -68
- smartsheet_python_sdk-4.0.0/tests/mock_api/reports/test_delete_report.py +77 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/reports/test_remove_report_scope.py +19 -28
- smartsheet_python_sdk-4.0.0/tests/mock_api/reports/test_update_report_definition.py +234 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/test_mock_api_sights.py +2 -1
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/test_mock_api_workspaces.py +26 -26
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/test_mock_serialization.py +1 -26
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/test_enumerated_value_set.py +6 -6
- smartsheet_python_sdk-4.0.0/uv.lock +3225 -0
- smartsheet_python_sdk-3.9.0/ADVANCED.md +0 -263
- smartsheet_python_sdk-3.9.0/Makefile +0 -57
- smartsheet_python_sdk-3.9.0/PKG-INFO +0 -124
- smartsheet_python_sdk-3.9.0/docs-source/Makefile +0 -153
- smartsheet_python_sdk-3.9.0/docs-source/smartsheet_api.rst +0 -186
- smartsheet_python_sdk-3.9.0/docs-source/smartsheet_enums.rst +0 -322
- smartsheet_python_sdk-3.9.0/docs-source/smartsheet_exceptions.rst +0 -7
- smartsheet_python_sdk-3.9.0/docs-source/smartsheet_models.rst +0 -1042
- smartsheet_python_sdk-3.9.0/docs-source/smartsheet_types.rst +0 -7
- smartsheet_python_sdk-3.9.0/setup.cfg +0 -4
- smartsheet_python_sdk-3.9.0/smartsheet/models/share.py +0 -183
- smartsheet_python_sdk-3.9.0/smartsheet/sights.py +0 -425
- smartsheet_python_sdk-3.9.0/smartsheet/templates.py +0 -90
- smartsheet_python_sdk-3.9.0/smartsheet_python_sdk.egg-info/SOURCES.txt +0 -271
- smartsheet_python_sdk-3.9.0/smartsheet_python_sdk.egg-info/dependency_links.txt +0 -1
- smartsheet_python_sdk-3.9.0/smartsheet_python_sdk.egg-info/requires.txt +0 -30
- smartsheet_python_sdk-3.9.0/smartsheet_python_sdk.egg-info/top_level.txt +0 -1
- smartsheet_python_sdk-3.9.0/tests/mock_api/reports/test_update_report_definition.py +0 -408
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/.gitchangelog.rc +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/.gitchangelog.tpl +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/.github/pull_request_template.md +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/.markdownlint.json +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/.roo/roomotes.yml +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/ISSUE-FIRST.md +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/LICENSE.md +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/NOTICE +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/README.md +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/docs-source/conf.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/docs-source/index.rst +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/__init__.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/attachments.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/cells.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/contacts.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/discussions.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/events.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/exceptions.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/favorites.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/groups.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/home.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/images.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/access_token.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/account.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/alternate_email.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/asset_share.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/asset_shares_paginated_result.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/attachment.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/auto_number_format.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/automation_action.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/automation_rule.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/boolean_object_value.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/bulk_item_failure.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/bulk_item_result.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/cell.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/cell_data_item.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/cell_history.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/cell_link.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/cell_link_widget_content.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/chart_widget_content.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/column.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/comment.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/contact.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/contact_object_value.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/container_destination.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/copy_or_move_row_destination.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/copy_or_move_row_directive.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/copy_or_move_row_result.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/create_report_request.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/criteria.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/cross_sheet_reference.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/currency.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/date_object_value.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/datetime_object_value.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/discussion.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/downloaded_file.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/duration.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/email.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/__init__.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/access_level.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/asset_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/attachment_parent_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/attachment_sub_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/attachment_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/automation_action_frequency.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/automation_action_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/automation_rule_disabled_reason.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/cell_link_status.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/column_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/criteria_target.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/cross_sheet_reference_status.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/currency_code.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/day_descriptors.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/day_ordinal.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/event_action.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/event_object_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/event_source.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/favorite_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/global_template.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/operator.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/paper_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/predecessor_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/publish_accessible_by.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/report_aggregation_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/report_asset_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/report_boolean_operator.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/report_destination_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/report_filter_operator.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/schedule_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/seat_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/share_scope.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/share_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/sheet_email_format.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/sheet_filter_operator.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/sheet_filter_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/sort_direction.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/symbol.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/system_column_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/update_request_status.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/user_status.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/enums/widget_type.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/error.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/error_result.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/event_result.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/explicit_null.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/favorite.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/folder.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/font_family.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/format_details.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/format_tables.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/group.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/group_member.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/home.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/hyperlink.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/image.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/image_url.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/image_url_map.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/image_widget_content.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/index_result.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/json_object.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/multi_contact_object_value.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/multi_picklist_object_value.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/multi_row_email.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/number_object_value.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/o_auth_error.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/object_value.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/paginated_children_result.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/predecessor.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/predecessor_list.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/primitive_object_value.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/profile_image.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/project_settings.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/recipient.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report_cell.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report_column.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report_column_identifier.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report_definition.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report_filter_criterion.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report_filter_expression.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report_grouping_criterion.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report_publish.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report_row.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report_sorting_criterion.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report_summarizing_criterion.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/report_widget_content.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/result.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/row.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/row_email.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/row_mapping.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/schedule.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/scope.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/search_result.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/search_result_item.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/selection_range.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/sent_update_request.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/server_info.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/sheet_email.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/sheet_filter.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/sheet_filter_details.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/sheet_publish.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/sheet_summary.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/sheet_user_permissions.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/sheet_user_settings.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/shortcut_data_item.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/shortcut_widget_content.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/sight.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/sight_publish.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/sort_criterion.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/sort_specifier.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/source.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/string_object_value.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/summary_field.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/template.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/title_rich_text_widget_content.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/token_paginated_result.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/update_request.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/user.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/user_model.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/user_plan.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/user_profile.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/version.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/web_content_widget_content.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/webhook.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/webhook_secret.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/webhook_stats.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/webhook_subscope.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/widget.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/widget_content.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/widget_hyperlink.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/models/workspace.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/object_value.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/passthrough.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/search.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/server.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/session.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/sharing.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/token.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/smartsheet/users.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/__init__.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/__init__.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/favorites/__init__.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/favorites/common_test_constants.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/favorites/test_is_favorite.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/mock_api_test_helper.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/test_mock_api_automation_rules.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/test_mock_api_columns.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/test_mock_api_folders.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/test_mock_api_reports.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/test_mock_api_rows.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/test_mock_api_sharing.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/test_mock_api_sheets.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/test_mock_change_agent.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/users/common_test_constants.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/users/test_deactivate_user.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/users/test_list_user_plans.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/users/test_list_users.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/users/test_reactivate_user.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/users/test_remove_user_from_plan.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/mock_api/users/test_user_upgrade_downgrade.py +0 -0
- {smartsheet_python_sdk-3.9.0 → smartsheet_python_sdk-4.0.0}/tests/test_util_serialize_dict.py +0 -0
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: implement-api-endpoint
|
|
3
|
+
description: Use when adding or modifying API endpoints in smartsheet-python-sdk - implementing resource methods, handling request/response serialization, or updating endpoint parameters
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Implement API Endpoint
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Complete workflow for implementing SDK endpoints: resource method, model objects, serialization, comprehensive tests (5 required types), and documentation. **Implementation alone is ~20% of the work.**
|
|
11
|
+
|
|
12
|
+
**CRITICAL REQUIREMENTS:**
|
|
13
|
+
1. You MUST use TodoWrite to create a todo for EACH checklist item below before starting implementation
|
|
14
|
+
2. You MUST have OpenAPI spec for the endpoint (Smartsheet public API: https://developers.smartsheet.com/_spec/api/smartsheet/openapi.json OR user-provided spec path)
|
|
15
|
+
3. Implementation MUST exactly match the spec (parameters, types, request/response structure)
|
|
16
|
+
|
|
17
|
+
## When to Use
|
|
18
|
+
|
|
19
|
+
- Adding new SDK endpoint (GET, POST, PUT, DELETE, PATCH)
|
|
20
|
+
- Modifying existing endpoint (parameters, return type, behavior)
|
|
21
|
+
- Updating endpoint for API changes
|
|
22
|
+
|
|
23
|
+
**GOLD STANDARD TEMPLATE: tests/mock_api/reports/**
|
|
24
|
+
**Before implementing, review report tests as your reference implementation. Follow these patterns exactly.**
|
|
25
|
+
|
|
26
|
+
**Not done until:** All 4 components exist (code, tests, WireMock mappings, docs) AND verified against OpenAPI spec
|
|
27
|
+
|
|
28
|
+
## Core Pattern
|
|
29
|
+
|
|
30
|
+
SDK endpoints require 4 components in order:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
1. Resource Method (smartsheet/{resource}.py)
|
|
34
|
+
2. Mock API Tests (tests/mock_api/{resource}/)
|
|
35
|
+
3. WireMock Mappings (smartsheet-sdk-tests repo)
|
|
36
|
+
4. Documentation (docs-source/)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Implementation is NOT done until all 4 exist.**
|
|
40
|
+
|
|
41
|
+
## Implementation Checklist
|
|
42
|
+
|
|
43
|
+
**STOP: Before writing ANY code:**
|
|
44
|
+
|
|
45
|
+
1. **Obtain OpenAPI spec:**
|
|
46
|
+
- Use Smartsheet public API spec: https://developers.smartsheet.com/_spec/api/smartsheet/openapi.json
|
|
47
|
+
- OR if endpoint not documented there, request spec path from user
|
|
48
|
+
- **Cannot proceed without spec - ask user if not provided**
|
|
49
|
+
|
|
50
|
+
2. **Obtain WireMock mappings:**
|
|
51
|
+
- Use Smartsheet SDK tests repo: https://github.com/smartsheet/smartsheet-sdk-tests
|
|
52
|
+
- OR request local filesystem path from user
|
|
53
|
+
- **Cannot proceed without mappings - ask user if not provided**
|
|
54
|
+
|
|
55
|
+
3. **Use TodoWrite to create a todo for EVERY checkbox below**
|
|
56
|
+
|
|
57
|
+
**Violating these rules means incomplete/incorrect work. Always verify spec and mappings first, create todos second.**
|
|
58
|
+
|
|
59
|
+
### 0. OpenAPI Spec Verification
|
|
60
|
+
|
|
61
|
+
**MUST be completed before implementation:**
|
|
62
|
+
|
|
63
|
+
- [ ] OpenAPI spec obtained (public API URL or user-provided path)
|
|
64
|
+
- [ ] Endpoint exists in spec with correct path
|
|
65
|
+
- [ ] HTTP method matches spec
|
|
66
|
+
- [ ] Request parameters match spec (names, types, required/optional)
|
|
67
|
+
- [ ] Request body schema matches spec (for POST/PUT/PATCH)
|
|
68
|
+
- [ ] Response schema matches spec (structure, property types)
|
|
69
|
+
- [ ] Error responses documented in spec
|
|
70
|
+
- [ ] Query parameters match spec (names, types, format)
|
|
71
|
+
|
|
72
|
+
### 0b. WireMock Mappings Verification
|
|
73
|
+
|
|
74
|
+
**MUST be obtained before implementation:**
|
|
75
|
+
|
|
76
|
+
- [ ] WireMock mappings obtained from:
|
|
77
|
+
- Smartsheet SDK tests repo: https://github.com/smartsheet/smartsheet-sdk-tests
|
|
78
|
+
- OR user-provided path on local filesystem
|
|
79
|
+
- [ ] **Cannot proceed without mappings - ask user if not provided**
|
|
80
|
+
- [ ] Mapping exists for: `/{resource}/{method}/all-response-body-properties`
|
|
81
|
+
- [ ] Mapping exists for: `/{resource}/{method}/required-response-body-properties` (if applicable)
|
|
82
|
+
- [ ] Global error mappings verified: `/errors/400-response`, `/errors/500-response`
|
|
83
|
+
- [ ] Response jsonBody in mappings matches OpenAPI spec schema
|
|
84
|
+
- [ ] Request body schema in mappings matches OpenAPI spec (for POST/PUT/PATCH)
|
|
85
|
+
|
|
86
|
+
### 1. Resource Method Implementation
|
|
87
|
+
|
|
88
|
+
**File:** `smartsheet/{resource}.py`
|
|
89
|
+
|
|
90
|
+
**ALL items must match OpenAPI spec exactly:**
|
|
91
|
+
|
|
92
|
+
- [ ] **Type definitions created** for request/response models (MANDATORY for new endpoints)
|
|
93
|
+
- [ ] **Python 3.7 compatibility verified** - type hints, syntax, no 3.8+ features
|
|
94
|
+
- [ ] Method signature with proper type hints (parameter types from spec)
|
|
95
|
+
- [ ] Parameter names match spec (snake_case conversion from camelCase)
|
|
96
|
+
- [ ] Required vs optional parameters match spec
|
|
97
|
+
- [ ] Docstring with Args and Returns sections (descriptions from spec)
|
|
98
|
+
- [ ] Create operation: `_op = fresh_operation("method_name")`
|
|
99
|
+
- [ ] Set HTTP method from spec: `_op["method"] = "GET/POST/PUT/DELETE"`
|
|
100
|
+
- [ ] Set path with placeholders from spec: `_op["path"] = "/resource/{id}"`
|
|
101
|
+
- [ ] Add query params matching spec: `_op["query_params"]["param"] = value`
|
|
102
|
+
- [ ] Add request body matching spec schema (if POST/PUT/PATCH): `_op["json"] = payload`
|
|
103
|
+
- [ ] Define expected response type from spec: `expected = "ModelName"` or `["Result", "ModelName"]`
|
|
104
|
+
- [ ] Prepare and execute: `prepped = self._base.prepare_request(_op)` then `return self._base.request(prepped, expected, _op)`
|
|
105
|
+
- [ ] Return type from spec: `Union[ExpectedType, Error]`
|
|
106
|
+
- [ ] **All type definitions use Python 3.7 compatible syntax**
|
|
107
|
+
|
|
108
|
+
**Reference:** See @ADVANCED.md "Resource Module Organization" for delegation pattern
|
|
109
|
+
|
|
110
|
+
### 2. Mock API Tests (5 Required Types)
|
|
111
|
+
|
|
112
|
+
**File:** `tests/mock_api/{resource}/test_{method_name}.py`
|
|
113
|
+
|
|
114
|
+
**CRITICAL: All 5 test types MUST exist. Tests MUST strictly follow @TESTING.md standards. No exceptions - this is a MANDATORY checklist for development.**
|
|
115
|
+
|
|
116
|
+
**GOLD STANDARD: Use tests/mock_api/reports/ as your template. Copy the assertion patterns, structure, and style exactly.**
|
|
117
|
+
|
|
118
|
+
**Test data must match OpenAPI spec:**
|
|
119
|
+
- Request parameters use spec-defined types and formats
|
|
120
|
+
- Response assertions match spec schema exactly
|
|
121
|
+
- Error responses match spec error schemas
|
|
122
|
+
|
|
123
|
+
- [ ] **`test_{method}_generated_url_is_correct`**
|
|
124
|
+
- Use `uuid.uuid4().hex` for request_id
|
|
125
|
+
- Call `get_mock_api_client(test_scenario_name, request_id)`
|
|
126
|
+
- Execute SDK method
|
|
127
|
+
- Use `get_wiremock_request(request_id)` to retrieve actual request
|
|
128
|
+
- Parse URL with `urlparse()` and `parse_qs()`
|
|
129
|
+
- Assert complete query object: `assert query == {...}` (NOT property-by-property) [TESTING.md lines 73-74]
|
|
130
|
+
- **ALWAYS assert query parameters, even if empty:** `assert not query`
|
|
131
|
+
- Assert URL path matches expected
|
|
132
|
+
|
|
133
|
+
- [ ] **`test_{method}_all_response_properties`**
|
|
134
|
+
- Call SDK method with test scenario
|
|
135
|
+
- Assert response type with `isinstance(response, ExpectedType)`
|
|
136
|
+
- For wrapped responses (Result, IndexResult): assert BOTH wrapper and inner type
|
|
137
|
+
- Assert complete response: `assert response.to_dict() == {...}` (whole object, NOT properties)
|
|
138
|
+
- **Response structure must match OpenAPI spec schema exactly**
|
|
139
|
+
- Retrieve request with `get_wiremock_request(request_id)`
|
|
140
|
+
- Parse body with `json.loads(wiremock_request["body"])`
|
|
141
|
+
- Assert complete request body: `assert request_body == {...}`
|
|
142
|
+
- **ALWAYS assert request body, even if empty for GET/DELETE:** `assert not request_body`
|
|
143
|
+
- For POST/PUT/PATCH: **Request body must match OpenAPI spec schema (camelCase, correct types)**
|
|
144
|
+
|
|
145
|
+
- [ ] **`test_{method}_required_response_properties`** (if applicable)
|
|
146
|
+
- Same pattern as all_response_properties
|
|
147
|
+
- Only create if WireMock mapping exists for minimal response
|
|
148
|
+
- Tests SDK handles responses with only required fields
|
|
149
|
+
- **ALWAYS assert request body, even if empty for GET/DELETE:** `assert not request_body`
|
|
150
|
+
|
|
151
|
+
- [ ] **`test_{method}_error_4xx`**
|
|
152
|
+
- Use test scenario `/errors/400-response` (catch-all)
|
|
153
|
+
- Call SDK method
|
|
154
|
+
- Assert `isinstance(response, Error)`
|
|
155
|
+
|
|
156
|
+
- [ ] **`test_{method}_error_5xx`**
|
|
157
|
+
- Use test scenario `/errors/500-response` (catch-all)
|
|
158
|
+
- Call SDK method
|
|
159
|
+
- Assert `isinstance(response, Error)`
|
|
160
|
+
|
|
161
|
+
**Constants file:** `tests/mock_api/{resource}/common_test_constants.py`
|
|
162
|
+
- [ ] Add test constants for IDs, expected values, enums
|
|
163
|
+
|
|
164
|
+
**MANDATORY REFERENCE:**
|
|
165
|
+
- See @TESTING.md "Mock API Test Standards" for complete assertion rules
|
|
166
|
+
- **Use tests/mock_api/reports/ as your implementation template - copy the patterns exactly**
|
|
167
|
+
|
|
168
|
+
### 3. WireMock Mappings
|
|
169
|
+
|
|
170
|
+
**Repository:** [smartsheet-sdk-tests](https://github.com/smartsheet/smartsheet-sdk-tests)
|
|
171
|
+
|
|
172
|
+
**Required mappings:**
|
|
173
|
+
- [ ] `{resource}/{method}/all-response-body-properties.json`
|
|
174
|
+
- [ ] `{resource}/{method}/required-response-body-properties.json` (if applicable)
|
|
175
|
+
- [ ] Error mappings exist globally: `/errors/400-response`, `/errors/500-response`
|
|
176
|
+
|
|
177
|
+
**Mapping structure (must match OpenAPI spec):**
|
|
178
|
+
```json
|
|
179
|
+
{
|
|
180
|
+
"request": {
|
|
181
|
+
"urlPathTemplate": "/2.0/{resource}/{id}",
|
|
182
|
+
"method": "GET",
|
|
183
|
+
"headers": {
|
|
184
|
+
"Authorization": {"matches": "Bearer .*"},
|
|
185
|
+
"x-test-name": {"equalTo": "/{resource}/{method}/all-response-body-properties"},
|
|
186
|
+
"x-request-id": {"matches": ".*"}
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
"response": {
|
|
190
|
+
"status": 200,
|
|
191
|
+
"jsonBody": { /* Must match OpenAPI response schema */ }
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
- [ ] Response jsonBody matches OpenAPI spec response schema exactly
|
|
197
|
+
- [ ] Request body schema matches spec (for POST/PUT/PATCH mappings)
|
|
198
|
+
- [ ] Status codes match spec
|
|
199
|
+
|
|
200
|
+
### 4. Documentation Updates
|
|
201
|
+
|
|
202
|
+
**File:** `docs-source/smartsheet_api.rst` (for API resources)
|
|
203
|
+
|
|
204
|
+
- [ ] **Check if docs-source update required** (see @ADVANCED.md for when updates are needed)
|
|
205
|
+
- [ ] Add method to appropriate module section
|
|
206
|
+
- [ ] Follow automodule pattern: `.. automethod:: {ResourceClass}.{method_name}`
|
|
207
|
+
- [ ] Rebuild docs: `uv run sphinx-build -b html docs-source docs-source/_build/html`
|
|
208
|
+
- [ ] Verify in `docs-source/_build/html/index.html`
|
|
209
|
+
|
|
210
|
+
**Reference:** See @CONTRIBUTING.md "Documentation" section for file mappings and @ADVANCED.md for documentation requirements
|
|
211
|
+
|
|
212
|
+
## Quick Reference: SDK Patterns
|
|
213
|
+
|
|
214
|
+
| Endpoint Type | Request Body | Response Type | Test Count |
|
|
215
|
+
|---------------|--------------|---------------|------------|
|
|
216
|
+
| GET single | None | `Model` or Error | 5 (skip required if N/A) |
|
|
217
|
+
| GET list | None | `IndexResult[Model]` | 5 |
|
|
218
|
+
| POST | `_op["json"]` | `Result[Model]` | 5 (must test request body) |
|
|
219
|
+
| PUT | `_op["json"]` | `Result[Model]` | 5 (must test request body) |
|
|
220
|
+
| DELETE | None | `Result[None]` | 5 |
|
|
221
|
+
|
|
222
|
+
## Common Mistakes
|
|
223
|
+
|
|
224
|
+
| Mistake | Reality | Fix |
|
|
225
|
+
|---------|---------|-----|
|
|
226
|
+
| "I don't need the spec" | Cannot verify correctness without it | Get spec URL/path first |
|
|
227
|
+
| "Spec roughly matches" | SDK must match spec exactly | Verify every parameter/field |
|
|
228
|
+
| "Implementation done" | Tests + docs still needed (~80% of work) | Complete all 4 checklist sections |
|
|
229
|
+
| "Endpoint is production-ready" | Without tests? No, it's 20% done | All 5 test types required |
|
|
230
|
+
| "I'll add tests later" | Tests verify correctness NOW | Tests before marking complete |
|
|
231
|
+
| Skipping TodoWrite | Incomplete work looks complete | Create todos FIRST, always |
|
|
232
|
+
| Property-by-property assertions | Allows extra properties to creep in | Use `.to_dict() == {...}` |
|
|
233
|
+
| Missing request body assertions | Request serialization bugs undetected | Assert `request_body == {...}` for POST/PUT/PATCH |
|
|
234
|
+
| Skipping error tests | Error handling untested | Both 4xx and 5xx required |
|
|
235
|
+
| Only 3 of 5 test types | Incomplete coverage | All 5 types MUST exist |
|
|
236
|
+
| "Docs are obvious" | Sphinx won't auto-discover | Must add to .rst files |
|
|
237
|
+
| "Quick implementation" without todos | 80% of work gets skipped | Todos first, no exceptions |
|
|
238
|
+
| Tests don't match TESTING.md | Standards exist for a reason | Follow @TESTING.md strictly |
|
|
239
|
+
| "I don't need WireMock mappings yet" | Tests will fail without them | Get mappings location first |
|
|
240
|
+
| "Mappings can be created later" | Tests depend on mappings existing | Mappings prerequisite, not optional |
|
|
241
|
+
| Missing type definitions | Type definitions MANDATORY for new endpoints | Create type defs first |
|
|
242
|
+
| Using Python 3.8+ features | Must support 3.7 | Check syntax compatibility |
|
|
243
|
+
| Skipping docs check | ADVANCED.md defines requirements | Verify docs needed |
|
|
244
|
+
|
|
245
|
+
## Red Flags - STOP and Complete Checklist
|
|
246
|
+
|
|
247
|
+
These thoughts mean STOP - you're taking shortcuts:
|
|
248
|
+
|
|
249
|
+
- **No OpenAPI spec verified** - Cannot proceed without spec
|
|
250
|
+
- **No WireMock mappings verified** - Cannot proceed without mappings
|
|
251
|
+
- **Haven't reviewed reports tests** - Must review gold standard template first
|
|
252
|
+
- "I'll check the spec later" - Spec MUST be verified first
|
|
253
|
+
- "I know the pattern" - Review reports tests anyway, don't rely on memory
|
|
254
|
+
- "Mappings probably exist" - Must verify, not assume
|
|
255
|
+
- Only implementation file changed (no tests/docs)
|
|
256
|
+
- "Implementation complete" or "endpoint is production-ready"
|
|
257
|
+
- "Quick implementation" without TodoWrite
|
|
258
|
+
- No todos created from checklist
|
|
259
|
+
- Missing any of 5 test types
|
|
260
|
+
- WireMock mappings not created
|
|
261
|
+
- Tests use property-by-property assertions
|
|
262
|
+
- Documentation not updated
|
|
263
|
+
- "I'll add tests/docs in follow-up PR"
|
|
264
|
+
- "Tests can wait" or "just need implementation"
|
|
265
|
+
- Started coding before creating todos
|
|
266
|
+
- Request/response doesn't match spec exactly
|
|
267
|
+
- No type definitions created for new endpoint
|
|
268
|
+
- Using Python 3.8+ syntax (walrus operator, positional-only params)
|
|
269
|
+
- Didn't check ADVANCED.md for docs requirements
|
|
270
|
+
|
|
271
|
+
**All of these mean: Work incomplete. Return to checklist, verify spec and mappings, create ALL todos first.**
|
|
272
|
+
|
|
273
|
+
**Implementation without spec verification, mappings, tests, and docs is NOT production-ready. It's 20% done.**
|
|
274
|
+
|
|
275
|
+
## Example: Complete Implementation
|
|
276
|
+
|
|
277
|
+
**NOTE: This is a simplified example. For complete gold standard implementation, see tests/mock_api/reports/test_create_report.py**
|
|
278
|
+
|
|
279
|
+
**Scenario:** Add `Contacts.get_contact(contact_id)`
|
|
280
|
+
|
|
281
|
+
### 1. Resource Method
|
|
282
|
+
```python
|
|
283
|
+
# smartsheet/contacts.py
|
|
284
|
+
def get_contact(self, contact_id: str) -> Union[Contact, Error]:
|
|
285
|
+
"""Get a contact by ID.
|
|
286
|
+
|
|
287
|
+
Args:
|
|
288
|
+
contact_id (str): Contact ID (email address)
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
Union[Contact, Error]: Contact object or Error
|
|
292
|
+
"""
|
|
293
|
+
_op = fresh_operation("get_contact")
|
|
294
|
+
_op["method"] = "GET"
|
|
295
|
+
_op["path"] = f"/contacts/{contact_id}"
|
|
296
|
+
|
|
297
|
+
expected = "Contact"
|
|
298
|
+
prepped = self._base.prepare_request(_op)
|
|
299
|
+
return self._base.request(prepped, expected, _op)
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### 2. Tests (5 types)
|
|
303
|
+
```python
|
|
304
|
+
# tests/mock_api/contacts/test_get_contact.py
|
|
305
|
+
import uuid
|
|
306
|
+
from urllib.parse import urlparse
|
|
307
|
+
from smartsheet.models import Contact, Error
|
|
308
|
+
from tests.mock_api.mock_api_test_helper import (
|
|
309
|
+
get_mock_api_client, get_wiremock_request
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
def test_get_contact_generated_url_is_correct():
|
|
313
|
+
request_id = uuid.uuid4().hex
|
|
314
|
+
client = get_mock_api_client(
|
|
315
|
+
"/contacts/get-contact/all-response-body-properties", request_id
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
client.Contacts.get_contact("user@example.com")
|
|
319
|
+
|
|
320
|
+
wiremock_request = get_wiremock_request(request_id)
|
|
321
|
+
url = urlparse(wiremock_request["absoluteUrl"])
|
|
322
|
+
assert url.path == "/2.0/contacts/user@example.com"
|
|
323
|
+
|
|
324
|
+
def test_get_contact_all_response_properties():
|
|
325
|
+
request_id = uuid.uuid4().hex
|
|
326
|
+
client = get_mock_api_client(
|
|
327
|
+
"/contacts/get-contact/all-response-body-properties", request_id
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
response = client.Contacts.get_contact("user@example.com")
|
|
331
|
+
|
|
332
|
+
assert isinstance(response, Contact)
|
|
333
|
+
assert response.to_dict() == {
|
|
334
|
+
"id": "user@example.com",
|
|
335
|
+
"email": "user@example.com",
|
|
336
|
+
"name": "User Name"
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
def test_get_contact_error_4xx():
|
|
340
|
+
request_id = uuid.uuid4().hex
|
|
341
|
+
client = get_mock_api_client("/errors/400-response", request_id)
|
|
342
|
+
|
|
343
|
+
response = client.Contacts.get_contact("invalid")
|
|
344
|
+
assert isinstance(response, Error)
|
|
345
|
+
|
|
346
|
+
def test_get_contact_error_5xx():
|
|
347
|
+
request_id = uuid.uuid4().hex
|
|
348
|
+
client = get_mock_api_client("/errors/500-response", request_id)
|
|
349
|
+
|
|
350
|
+
response = client.Contacts.get_contact("user@example.com")
|
|
351
|
+
assert isinstance(response, Error)
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### 3. Documentation
|
|
355
|
+
```rst
|
|
356
|
+
# docs-source/smartsheet_api.rst
|
|
357
|
+
Contacts
|
|
358
|
+
--------
|
|
359
|
+
.. automethod:: Contacts.get_contact
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## The Bottom Line
|
|
363
|
+
|
|
364
|
+
**Implementation without tests and documentation is incomplete work.**
|
|
365
|
+
|
|
366
|
+
The baseline pattern: agents write implementation quickly, then stop at ~20% complete. Time pressure triggers "implementation = done" rationalization.
|
|
367
|
+
|
|
368
|
+
Follow the 4-part checklist completely. All 5 test types are required. Whole-object assertions prevent regressions. Documentation updates are not optional.
|
|
369
|
+
|
|
370
|
+
**No Exceptions:**
|
|
371
|
+
- Not for "simple endpoints" - all require tests
|
|
372
|
+
- Not for "modifications" - updated endpoints need updated tests
|
|
373
|
+
- Not for "time pressure" - incomplete work creates more pressure later
|
|
374
|
+
- Not for "stakeholder waiting" - shipping untested code is worse
|
|
375
|
+
- Never skip TodoWrite - creates accountability
|
|
376
|
+
|
|
377
|
+
**The rule: Create ALL todos from checklist FIRST. Then complete them. Mark done only when all 4 components exist.**
|