asana-api-cli 1.4.0__tar.gz → 1.5.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.
Files changed (71) hide show
  1. {asana_api_cli-1.4.0/src/asana_api_cli.egg-info → asana_api_cli-1.5.0}/PKG-INFO +67 -11
  2. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/README.md +66 -10
  3. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/pyproject.toml +2 -1
  4. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/__init__.py +0 -3
  5. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/allocations.py +16 -6
  6. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/attachments.py +16 -6
  7. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/audit_log_api.py +16 -6
  8. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/custom_field_settings.py +48 -18
  9. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/custom_fields.py +16 -6
  10. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/custom_types.py +16 -6
  11. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/goal_relationships.py +16 -6
  12. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/goals.py +16 -6
  13. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/memberships.py +16 -6
  14. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/portfolio_memberships.py +32 -12
  15. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/portfolios.py +32 -12
  16. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/project_memberships.py +16 -6
  17. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/project_portfolio_settings.py +32 -12
  18. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/project_statuses.py +16 -6
  19. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/project_templates.py +32 -12
  20. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/projects.py +64 -24
  21. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/rates.py +16 -6
  22. asana_api_cli-1.5.0/src/asana_api_cli/cli/reactions.py +45 -0
  23. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/roles.py +16 -6
  24. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/sections.py +16 -6
  25. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/status_updates.py +32 -12
  26. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/stories.py +32 -12
  27. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/tags.py +48 -18
  28. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/task_templates.py +16 -6
  29. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/tasks.py +128 -48
  30. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/team_memberships.py +48 -18
  31. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/teams.py +32 -12
  32. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/time_periods.py +16 -6
  33. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/time_tracking_categories.py +32 -12
  34. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/time_tracking_entries.py +32 -12
  35. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/timesheet_approval_statuses.py +16 -6
  36. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/users.py +32 -12
  37. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/webhooks.py +16 -6
  38. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/workspace_memberships.py +32 -12
  39. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/workspaces.py +16 -6
  40. asana_api_cli-1.5.0/src/asana_api_cli/click_ext.py +276 -0
  41. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/session.py +53 -6
  42. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0/src/asana_api_cli.egg-info}/PKG-INFO +67 -11
  43. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli.egg-info/SOURCES.txt +2 -0
  44. asana_api_cli-1.5.0/tests/test_click_ext.py +176 -0
  45. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/tests/test_codegen.py +37 -5
  46. asana_api_cli-1.5.0/tests/test_py310_compat.py +41 -0
  47. asana_api_cli-1.4.0/src/asana_api_cli/cli/reactions.py +0 -35
  48. asana_api_cli-1.4.0/src/asana_api_cli/click_ext.py +0 -109
  49. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/LICENSE +0 -0
  50. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/setup.cfg +0 -0
  51. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/__init__.py +0 -0
  52. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/access_requests.py +0 -0
  53. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/batch_api.py +0 -0
  54. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/budgets.py +0 -0
  55. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/events.py +0 -0
  56. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/exports.py +0 -0
  57. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/jobs.py +0 -0
  58. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/organization_exports.py +0 -0
  59. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/project_briefs.py +0 -0
  60. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/rules.py +0 -0
  61. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/typeahead.py +0 -0
  62. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/cli/user_task_lists.py +0 -0
  63. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/formatter.py +0 -0
  64. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli/version.py +0 -0
  65. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli.egg-info/dependency_links.txt +0 -0
  66. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli.egg-info/entry_points.txt +0 -0
  67. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli.egg-info/requires.txt +0 -0
  68. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/src/asana_api_cli.egg-info/top_level.txt +0 -0
  69. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/tests/test_formatter.py +0 -0
  70. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/tests/test_session.py +0 -0
  71. {asana_api_cli-1.4.0 → asana_api_cli-1.5.0}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: asana-api-cli
3
- Version: 1.4.0
3
+ Version: 1.5.0
4
4
  Summary: Command-line wrapper around the official Asana Python SDK
5
5
  Author-email: Masanao Izumo <asana@masanao.site>
6
6
  License-Expression: MIT
@@ -66,28 +66,27 @@ and add the line to `~/.zshrc` or `~/.config/fish/config.fish` respectively.
66
66
  ## Usage
67
67
 
68
68
  ```bash
69
- # Show version
69
+ # Version and help
70
70
  asana-api --version
71
-
72
- # List commands
73
71
  asana-api --help
74
72
  asana-api tasks --help
75
73
  asana-api tasks get-tasks --help
76
74
 
77
- # List workspaces
75
+ # List workspaces and projects
78
76
  asana-api workspaces get-workspaces
79
-
80
- # List projects (workspace resolved from ASANA_DEFAULT_WORKSPACE)
81
77
  asana-api projects get-projects-for-workspace
82
78
  asana-api projects get-projects --workspace <WORKSPACE_GID>
83
79
 
84
- # List tasks (first page)
80
+ # List tasks (first page only by default)
85
81
  asana-api tasks get-tasks --project <PROJECT_GID>
86
82
 
87
- # Auto-fetch all pages
88
- asana-api tasks get-tasks --project <PROJECT_GID> --paginate
83
+ # Preview the first few items
84
+ asana-api tasks get-tasks --project <PROJECT_GID> --max-items 5
85
+
86
+ # Fetch every item across pages
87
+ asana-api tasks get-tasks --project <PROJECT_GID> --all-items
89
88
 
90
- # Single task (--task instead of positional argument)
89
+ # Single task
91
90
  asana-api tasks get-task --task <TASK_GID>
92
91
 
93
92
  # Create a task (body is a JSON string)
@@ -98,6 +97,9 @@ asana-api tasks get-tasks --project <PID> --output table
98
97
  asana-api tasks get-tasks --project <PID> --query '.data' --output csv
99
98
  ```
100
99
 
100
+ See [Pagination](#pagination) for fetching across pages and
101
+ [Global options](#global-options) for `--debug`, `--access-token`, etc.
102
+
101
103
  ### Workspace resolution
102
104
 
103
105
  Many API endpoints require a workspace. For those endpoints (e.g.
@@ -111,6 +113,60 @@ fallback is **not** used — pass `--workspace` explicitly if needed. This
111
113
  prevents conflicts with other scope parameters like `--project` that are
112
114
  mutually exclusive with workspace in the Asana API.
113
115
 
116
+ ## Pagination
117
+
118
+ Listing endpoints (e.g. `tasks get-tasks`) return paginated results. The CLI
119
+ provides four ways to control how much is fetched:
120
+
121
+ | Option | Behavior |
122
+ |--------|----------|
123
+ | (none) | Fetch a single page (Asana default: 100 items) |
124
+ | `--max-items N` | Fetch up to N items, auto-paginating across pages. The last request is automatically capped to the remaining count. |
125
+ | `--all-items` | Fetch every page until the server reports no more |
126
+ | `--offset <TOKEN>` | Manual pagination: pass the `next_page.offset` token from the previous response |
127
+
128
+ `--max-items` and `--all-items` are mutually exclusive.
129
+
130
+ `--page-size N` tunes the per-page request size (Asana API requires 1-100,
131
+ default 100). Rarely needed — combine with `--all-items` or `--max-items` only
132
+ when the default doesn't suit (e.g. very large rows or rate-limit tuning).
133
+
134
+ ```bash
135
+ # Auto-paginate up to 250 items
136
+ asana-api tasks get-tasks --project <PID> --max-items 250
137
+
138
+ # Fetch everything
139
+ asana-api tasks get-tasks --project <PID> --all-items
140
+
141
+ # Manual pagination using the offset token
142
+ asana-api tasks get-tasks --project <PID> --offset <TOKEN>
143
+ ```
144
+
145
+ ## Global options
146
+
147
+ These options work at any level of the command tree, so the following are
148
+ equivalent:
149
+
150
+ ```bash
151
+ asana-api --debug tasks get-tasks --project <PID>
152
+ asana-api tasks get-tasks --project <PID> --debug
153
+ ```
154
+
155
+ When the same option is given at multiple levels, the more specific (later)
156
+ one wins.
157
+
158
+ | Option | Description |
159
+ |--------|-------------|
160
+ | `--access-token TOKEN` | Asana personal access token (default: `$ASANA_ACCESS_TOKEN`) |
161
+ | `--host URL` | Override API base URL (default: `https://app.asana.com/api/1.0`) |
162
+ | `--proxy URL` | HTTP/HTTPS proxy URL |
163
+ | `--no-verify-ssl` | Disable TLS certificate verification (insecure) |
164
+ | `--ca-cert PATH` | Path to a PEM bundle of trusted CA certificates |
165
+ | `--retries N` | Number of retries on 429/5xx responses (default: 5) |
166
+ | `--timeout SECONDS` | Per-request timeout in seconds |
167
+ | `--temp-dir PATH` | Directory for temporary downloads |
168
+ | `--debug` | Print HTTP request/response to stderr for troubleshooting |
169
+
114
170
  ## Development
115
171
 
116
172
  See [docs/development.md](https://github.com/izumo-m/asana-api-cli/blob/main/docs/development.md)
@@ -47,28 +47,27 @@ and add the line to `~/.zshrc` or `~/.config/fish/config.fish` respectively.
47
47
  ## Usage
48
48
 
49
49
  ```bash
50
- # Show version
50
+ # Version and help
51
51
  asana-api --version
52
-
53
- # List commands
54
52
  asana-api --help
55
53
  asana-api tasks --help
56
54
  asana-api tasks get-tasks --help
57
55
 
58
- # List workspaces
56
+ # List workspaces and projects
59
57
  asana-api workspaces get-workspaces
60
-
61
- # List projects (workspace resolved from ASANA_DEFAULT_WORKSPACE)
62
58
  asana-api projects get-projects-for-workspace
63
59
  asana-api projects get-projects --workspace <WORKSPACE_GID>
64
60
 
65
- # List tasks (first page)
61
+ # List tasks (first page only by default)
66
62
  asana-api tasks get-tasks --project <PROJECT_GID>
67
63
 
68
- # Auto-fetch all pages
69
- asana-api tasks get-tasks --project <PROJECT_GID> --paginate
64
+ # Preview the first few items
65
+ asana-api tasks get-tasks --project <PROJECT_GID> --max-items 5
66
+
67
+ # Fetch every item across pages
68
+ asana-api tasks get-tasks --project <PROJECT_GID> --all-items
70
69
 
71
- # Single task (--task instead of positional argument)
70
+ # Single task
72
71
  asana-api tasks get-task --task <TASK_GID>
73
72
 
74
73
  # Create a task (body is a JSON string)
@@ -79,6 +78,9 @@ asana-api tasks get-tasks --project <PID> --output table
79
78
  asana-api tasks get-tasks --project <PID> --query '.data' --output csv
80
79
  ```
81
80
 
81
+ See [Pagination](#pagination) for fetching across pages and
82
+ [Global options](#global-options) for `--debug`, `--access-token`, etc.
83
+
82
84
  ### Workspace resolution
83
85
 
84
86
  Many API endpoints require a workspace. For those endpoints (e.g.
@@ -92,6 +94,60 @@ fallback is **not** used — pass `--workspace` explicitly if needed. This
92
94
  prevents conflicts with other scope parameters like `--project` that are
93
95
  mutually exclusive with workspace in the Asana API.
94
96
 
97
+ ## Pagination
98
+
99
+ Listing endpoints (e.g. `tasks get-tasks`) return paginated results. The CLI
100
+ provides four ways to control how much is fetched:
101
+
102
+ | Option | Behavior |
103
+ |--------|----------|
104
+ | (none) | Fetch a single page (Asana default: 100 items) |
105
+ | `--max-items N` | Fetch up to N items, auto-paginating across pages. The last request is automatically capped to the remaining count. |
106
+ | `--all-items` | Fetch every page until the server reports no more |
107
+ | `--offset <TOKEN>` | Manual pagination: pass the `next_page.offset` token from the previous response |
108
+
109
+ `--max-items` and `--all-items` are mutually exclusive.
110
+
111
+ `--page-size N` tunes the per-page request size (Asana API requires 1-100,
112
+ default 100). Rarely needed — combine with `--all-items` or `--max-items` only
113
+ when the default doesn't suit (e.g. very large rows or rate-limit tuning).
114
+
115
+ ```bash
116
+ # Auto-paginate up to 250 items
117
+ asana-api tasks get-tasks --project <PID> --max-items 250
118
+
119
+ # Fetch everything
120
+ asana-api tasks get-tasks --project <PID> --all-items
121
+
122
+ # Manual pagination using the offset token
123
+ asana-api tasks get-tasks --project <PID> --offset <TOKEN>
124
+ ```
125
+
126
+ ## Global options
127
+
128
+ These options work at any level of the command tree, so the following are
129
+ equivalent:
130
+
131
+ ```bash
132
+ asana-api --debug tasks get-tasks --project <PID>
133
+ asana-api tasks get-tasks --project <PID> --debug
134
+ ```
135
+
136
+ When the same option is given at multiple levels, the more specific (later)
137
+ one wins.
138
+
139
+ | Option | Description |
140
+ |--------|-------------|
141
+ | `--access-token TOKEN` | Asana personal access token (default: `$ASANA_ACCESS_TOKEN`) |
142
+ | `--host URL` | Override API base URL (default: `https://app.asana.com/api/1.0`) |
143
+ | `--proxy URL` | HTTP/HTTPS proxy URL |
144
+ | `--no-verify-ssl` | Disable TLS certificate verification (insecure) |
145
+ | `--ca-cert PATH` | Path to a PEM bundle of trusted CA certificates |
146
+ | `--retries N` | Number of retries on 429/5xx responses (default: 5) |
147
+ | `--timeout SECONDS` | Per-request timeout in seconds |
148
+ | `--temp-dir PATH` | Directory for temporary downloads |
149
+ | `--debug` | Print HTTP request/response to stderr for troubleshooting |
150
+
95
151
  ## Development
96
152
 
97
153
  See [docs/development.md](https://github.com/izumo-m/asana-api-cli/blob/main/docs/development.md)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "asana-api-cli"
3
- version = "1.4.0"
3
+ version = "1.5.0"
4
4
  description = "Command-line wrapper around the official Asana Python SDK"
5
5
  authors = [{name = "Masanao Izumo", email = "asana@masanao.site"}]
6
6
  readme = "README.md"
@@ -28,6 +28,7 @@ dev = [
28
28
  "pytest>=9,<10",
29
29
  "build>=1,<2",
30
30
  "twine>=6,<7",
31
+ "vermin>=1.6,<2",
31
32
  ]
32
33
 
33
34
  [build-system]
@@ -64,7 +64,6 @@ LAZY_SUBCOMMANDS: dict[str, tuple[str, str]] = {
64
64
  @click.option("--proxy", default=None, help="HTTP/HTTPS proxy URL")
65
65
  @click.option("--no-verify-ssl", is_flag=True, default=False, help="Disable TLS certificate verification (insecure)")
66
66
  @click.option("--ca-cert", "ca_cert", default=None, type=click.Path(exists=True, dir_okay=False), help="Path to a PEM bundle of trusted CA certificates")
67
- @click.option("--page-limit", "page_limit", type=int, default=None, help="Default per-page size for paginated endpoints")
68
67
  @click.option("--retries", type=int, default=None, help="Number of retries on 429/5xx responses (default: 5)")
69
68
  @click.option("--timeout", type=float, default=None, help="Per-request timeout in seconds")
70
69
  @click.option("--access-token", "access_token", default=None, help="Asana personal access token (default: $ASANA_ACCESS_TOKEN)")
@@ -75,7 +74,6 @@ def main(
75
74
  proxy: str | None,
76
75
  no_verify_ssl: bool,
77
76
  ca_cert: str | None,
78
- page_limit: int | None,
79
77
  retries: int | None,
80
78
  timeout: float | None,
81
79
  access_token: str | None,
@@ -87,7 +85,6 @@ def main(
87
85
  runtime.proxy = proxy
88
86
  runtime.verify_ssl = not no_verify_ssl
89
87
  runtime.ssl_ca_cert = ca_cert
90
- runtime.page_limit = page_limit
91
88
  runtime.retries = retries
92
89
  runtime.timeout = timeout
93
90
  if access_token:
@@ -59,22 +59,30 @@ def get_allocation(allocation: str, opt_fields: str | None) -> Any:
59
59
  @allocations_group.command("get-allocations")
60
60
  @click.option("--workspace", default=None, help="Workspace GID (falls back to ASANA_DEFAULT_WORKSPACE)")
61
61
  @click.option("--assignee", default=None, help="Globally unique identifier for the user or placeholder the allocation is assigned to.")
62
- @click.option("--limit", type=int, default=None, help="Results per page. The number of objects to return per page. The value must be between 1 and 100.")
63
62
  @click.option("--offset", default=None, help="Offset token. An offset to the next page returned by the API. A pagination request will return an offset token, which can be used as an input parameter to the next request. If an offset is not pass...")
64
63
  @click.option("--opt-fields", default=None, help="This endpoint returns a resource which excludes some properties by default. To include those optional properties, set this query parameter to a comma-separated list of the properties you wish to in...")
65
64
  @click.option("--parent", default=None, help="Globally unique identifier for the project to filter allocations by.")
66
- @click.option("--paginate", is_flag=True, default=False, help="Fetch all pages")
65
+ @click.option("--all-items", "all_items", is_flag=True, default=False, help="Fetch all items (no cap)")
66
+ @click.option("--paginate", "paginate", is_flag=True, default=False, help="(Deprecated) Alias for --all-items")
67
+ @click.option("--page-size", "page_size", type=int, default=None, help="Items per page (Asana API requires 1-100, default 100)")
68
+ @click.option("--max-items", "max_items", type=int, default=None, help="Stop after fetching this many items in total")
67
69
  @formatted
68
- def get_allocations(workspace: str | None, assignee: str | None, limit: int | None, offset: str | None, opt_fields: str | None, parent: str | None, paginate: bool) -> Any:
70
+ def get_allocations(workspace: str | None, assignee: str | None, offset: str | None, opt_fields: str | None, parent: str | None, all_items: bool, paginate: bool, page_size: int | None, max_items: int | None) -> Any:
69
71
  """Get multiple allocations"""
70
72
  resolved_workspace = resolve_workspace(workspace, required=False)
71
- session = AsanaSession.from_env(paginate=paginate)
73
+ if paginate:
74
+ click.echo("Warning: --paginate is deprecated; use --all-items instead.", err=True)
75
+ fetch_all = all_items or paginate
76
+ if fetch_all and max_items is not None:
77
+ raise click.UsageError("--max-items cannot be combined with --all-items (or its deprecated alias --paginate)")
78
+ effective_page_size = page_size
79
+ if max_items is not None and (page_size is None or page_size > max_items):
80
+ effective_page_size = max_items
81
+ session = AsanaSession.from_env(paginate=fetch_all, page_size=effective_page_size)
72
82
  api = AllocationsApi(session.client)
73
83
  opts: dict[str, Any] = {}
74
84
  if assignee is not None:
75
85
  opts["assignee"] = assignee
76
- if limit is not None:
77
- opts["limit"] = limit
78
86
  if offset is not None:
79
87
  opts["offset"] = offset
80
88
  if opt_fields is not None:
@@ -83,6 +91,8 @@ def get_allocations(workspace: str | None, assignee: str | None, limit: int | No
83
91
  opts["parent"] = parent
84
92
  if resolved_workspace is not None:
85
93
  opts["workspace"] = resolved_workspace
94
+ if max_items is not None:
95
+ return session.fetch_capped(api.get_allocations, opts=opts, max_items=max_items)
86
96
  return api.get_allocations(opts)
87
97
 
88
98
 
@@ -74,20 +74,30 @@ def get_attachment(attachment: str, opt_fields: str | None) -> Any:
74
74
 
75
75
  @attachments_group.command("get-attachments-for-object")
76
76
  @click.option("--parent", required=True, help="Globally unique identifier for object to fetch statuses from. Must be a GID for a `project`, `project_brief`, or `task`.")
77
- @click.option("--limit", type=int, default=None, help="Results per page. The number of objects to return per page. The value must be between 1 and 100.")
78
77
  @click.option("--offset", default=None, help="Offset token. An offset to the next page returned by the API. A pagination request will return an offset token, which can be used as an input parameter to the next request. If an offset is not pass...")
79
78
  @click.option("--opt-fields", default=None, help="This endpoint returns a resource which excludes some properties by default. To include those optional properties, set this query parameter to a comma-separated list of the properties you wish to in...")
80
- @click.option("--paginate", is_flag=True, default=False, help="Fetch all pages")
79
+ @click.option("--all-items", "all_items", is_flag=True, default=False, help="Fetch all items (no cap)")
80
+ @click.option("--paginate", "paginate", is_flag=True, default=False, help="(Deprecated) Alias for --all-items")
81
+ @click.option("--page-size", "page_size", type=int, default=None, help="Items per page (Asana API requires 1-100, default 100)")
82
+ @click.option("--max-items", "max_items", type=int, default=None, help="Stop after fetching this many items in total")
81
83
  @formatted
82
- def get_attachments_for_object(parent: str, limit: int | None, offset: str | None, opt_fields: str | None, paginate: bool) -> Any:
84
+ def get_attachments_for_object(parent: str, offset: str | None, opt_fields: str | None, all_items: bool, paginate: bool, page_size: int | None, max_items: int | None) -> Any:
83
85
  """Get attachments from an object"""
84
- session = AsanaSession.from_env(paginate=paginate)
86
+ if paginate:
87
+ click.echo("Warning: --paginate is deprecated; use --all-items instead.", err=True)
88
+ fetch_all = all_items or paginate
89
+ if fetch_all and max_items is not None:
90
+ raise click.UsageError("--max-items cannot be combined with --all-items (or its deprecated alias --paginate)")
91
+ effective_page_size = page_size
92
+ if max_items is not None and (page_size is None or page_size > max_items):
93
+ effective_page_size = max_items
94
+ session = AsanaSession.from_env(paginate=fetch_all, page_size=effective_page_size)
85
95
  api = AttachmentsApi(session.client)
86
96
  opts: dict[str, Any] = {}
87
- if limit is not None:
88
- opts["limit"] = limit
89
97
  if offset is not None:
90
98
  opts["offset"] = offset
91
99
  if opt_fields is not None:
92
100
  opts["opt_fields"] = opt_fields
101
+ if max_items is not None:
102
+ return session.fetch_capped(api.get_attachments_for_object, parent, opts=opts, max_items=max_items)
93
103
  return api.get_attachments_for_object(parent, opts)
@@ -22,16 +22,26 @@ def audit_log_api_group() -> None:
22
22
  @click.option("--actor-type", default=None, help="Filter to events with an actor of this type. This only needs to be included if querying for actor types without an ID. If `actor_gid` is included, this should be excluded.")
23
23
  @click.option("--end-at", default=None, help="Filter to events created before this time (exclusive).")
24
24
  @click.option("--event-type", default=None, help="Filter to events of this type. Refer to the [supported audit log events](/docs/audit-log-events#supported-audit-log-events) for a full list of values.")
25
- @click.option("--limit", type=int, default=None, help="Results per page. The number of objects to return per page. The value must be between 1 and 100.")
26
25
  @click.option("--offset", default=None, help="Offset token. An offset to the next page returned by the API. A pagination request will return an offset token, which can be used as an input parameter to the next request. If an offset is not pass...")
27
26
  @click.option("--resource-gid", default=None, help="Filter to events with this resource ID.")
28
27
  @click.option("--start-at", default=None, help="Filter to events created after this time (inclusive).")
29
- @click.option("--paginate", is_flag=True, default=False, help="Fetch all pages")
28
+ @click.option("--all-items", "all_items", is_flag=True, default=False, help="Fetch all items (no cap)")
29
+ @click.option("--paginate", "paginate", is_flag=True, default=False, help="(Deprecated) Alias for --all-items")
30
+ @click.option("--page-size", "page_size", type=int, default=None, help="Items per page (Asana API requires 1-100, default 100)")
31
+ @click.option("--max-items", "max_items", type=int, default=None, help="Stop after fetching this many items in total")
30
32
  @formatted
31
- def get_audit_log_events(workspace: str | None, actor_gid: str | None, actor_type: str | None, end_at: str | None, event_type: str | None, limit: int | None, offset: str | None, resource_gid: str | None, start_at: str | None, paginate: bool) -> Any:
33
+ def get_audit_log_events(workspace: str | None, actor_gid: str | None, actor_type: str | None, end_at: str | None, event_type: str | None, offset: str | None, resource_gid: str | None, start_at: str | None, all_items: bool, paginate: bool, page_size: int | None, max_items: int | None) -> Any:
32
34
  """Get audit log events"""
33
35
  resolved_workspace = resolve_workspace(workspace, required=True)
34
- session = AsanaSession.from_env(paginate=paginate)
36
+ if paginate:
37
+ click.echo("Warning: --paginate is deprecated; use --all-items instead.", err=True)
38
+ fetch_all = all_items or paginate
39
+ if fetch_all and max_items is not None:
40
+ raise click.UsageError("--max-items cannot be combined with --all-items (or its deprecated alias --paginate)")
41
+ effective_page_size = page_size
42
+ if max_items is not None and (page_size is None or page_size > max_items):
43
+ effective_page_size = max_items
44
+ session = AsanaSession.from_env(paginate=fetch_all, page_size=effective_page_size)
35
45
  api = AuditLogAPIApi(session.client)
36
46
  opts: dict[str, Any] = {}
37
47
  if actor_gid is not None:
@@ -42,12 +52,12 @@ def get_audit_log_events(workspace: str | None, actor_gid: str | None, actor_typ
42
52
  opts["end_at"] = end_at
43
53
  if event_type is not None:
44
54
  opts["event_type"] = event_type
45
- if limit is not None:
46
- opts["limit"] = limit
47
55
  if offset is not None:
48
56
  opts["offset"] = offset
49
57
  if resource_gid is not None:
50
58
  opts["resource_gid"] = resource_gid
51
59
  if start_at is not None:
52
60
  opts["start_at"] = start_at
61
+ if max_items is not None:
62
+ return session.fetch_capped(api.get_audit_log_events, resolved_workspace, opts=opts, max_items=max_items)
53
63
  return api.get_audit_log_events(resolved_workspace, opts)
@@ -18,64 +18,94 @@ def custom_field_settings_group() -> None:
18
18
 
19
19
  @custom_field_settings_group.command("get-custom-field-settings-for-goal")
20
20
  @click.option("--goal", required=True, help="Globally unique identifier for the goal.")
21
- @click.option("--limit", type=int, default=None, help="Results per page. The number of objects to return per page. The value must be between 1 and 100.")
22
21
  @click.option("--offset", default=None, help="Offset token. An offset to the next page returned by the API. A pagination request will return an offset token, which can be used as an input parameter to the next request. If an offset is not pass...")
23
22
  @click.option("--opt-fields", default=None, help="This endpoint returns a resource which excludes some properties by default. To include those optional properties, set this query parameter to a comma-separated list of the properties you wish to in...")
24
- @click.option("--paginate", is_flag=True, default=False, help="Fetch all pages")
23
+ @click.option("--all-items", "all_items", is_flag=True, default=False, help="Fetch all items (no cap)")
24
+ @click.option("--paginate", "paginate", is_flag=True, default=False, help="(Deprecated) Alias for --all-items")
25
+ @click.option("--page-size", "page_size", type=int, default=None, help="Items per page (Asana API requires 1-100, default 100)")
26
+ @click.option("--max-items", "max_items", type=int, default=None, help="Stop after fetching this many items in total")
25
27
  @formatted
26
- def get_custom_field_settings_for_goal(goal: str, limit: int | None, offset: str | None, opt_fields: str | None, paginate: bool) -> Any:
28
+ def get_custom_field_settings_for_goal(goal: str, offset: str | None, opt_fields: str | None, all_items: bool, paginate: bool, page_size: int | None, max_items: int | None) -> Any:
27
29
  """Get a goal's custom fields"""
28
- session = AsanaSession.from_env(paginate=paginate)
30
+ if paginate:
31
+ click.echo("Warning: --paginate is deprecated; use --all-items instead.", err=True)
32
+ fetch_all = all_items or paginate
33
+ if fetch_all and max_items is not None:
34
+ raise click.UsageError("--max-items cannot be combined with --all-items (or its deprecated alias --paginate)")
35
+ effective_page_size = page_size
36
+ if max_items is not None and (page_size is None or page_size > max_items):
37
+ effective_page_size = max_items
38
+ session = AsanaSession.from_env(paginate=fetch_all, page_size=effective_page_size)
29
39
  api = CustomFieldSettingsApi(session.client)
30
40
  opts: dict[str, Any] = {}
31
- if limit is not None:
32
- opts["limit"] = limit
33
41
  if offset is not None:
34
42
  opts["offset"] = offset
35
43
  if opt_fields is not None:
36
44
  opts["opt_fields"] = opt_fields
45
+ if max_items is not None:
46
+ return session.fetch_capped(api.get_custom_field_settings_for_goal, goal, opts=opts, max_items=max_items)
37
47
  return api.get_custom_field_settings_for_goal(goal, opts)
38
48
 
39
49
 
40
50
  @custom_field_settings_group.command("get-custom-field-settings-for-portfolio")
41
51
  @click.option("--portfolio", required=True, help="Globally unique identifier for the portfolio.")
42
- @click.option("--limit", type=int, default=None, help="Results per page. The number of objects to return per page. The value must be between 1 and 100.")
43
52
  @click.option("--offset", default=None, help="Offset token. An offset to the next page returned by the API. A pagination request will return an offset token, which can be used as an input parameter to the next request. If an offset is not pass...")
44
53
  @click.option("--opt-fields", default=None, help="This endpoint returns a resource which excludes some properties by default. To include those optional properties, set this query parameter to a comma-separated list of the properties you wish to in...")
45
- @click.option("--paginate", is_flag=True, default=False, help="Fetch all pages")
54
+ @click.option("--all-items", "all_items", is_flag=True, default=False, help="Fetch all items (no cap)")
55
+ @click.option("--paginate", "paginate", is_flag=True, default=False, help="(Deprecated) Alias for --all-items")
56
+ @click.option("--page-size", "page_size", type=int, default=None, help="Items per page (Asana API requires 1-100, default 100)")
57
+ @click.option("--max-items", "max_items", type=int, default=None, help="Stop after fetching this many items in total")
46
58
  @formatted
47
- def get_custom_field_settings_for_portfolio(portfolio: str, limit: int | None, offset: str | None, opt_fields: str | None, paginate: bool) -> Any:
59
+ def get_custom_field_settings_for_portfolio(portfolio: str, offset: str | None, opt_fields: str | None, all_items: bool, paginate: bool, page_size: int | None, max_items: int | None) -> Any:
48
60
  """Get a portfolio's custom fields"""
49
- session = AsanaSession.from_env(paginate=paginate)
61
+ if paginate:
62
+ click.echo("Warning: --paginate is deprecated; use --all-items instead.", err=True)
63
+ fetch_all = all_items or paginate
64
+ if fetch_all and max_items is not None:
65
+ raise click.UsageError("--max-items cannot be combined with --all-items (or its deprecated alias --paginate)")
66
+ effective_page_size = page_size
67
+ if max_items is not None and (page_size is None or page_size > max_items):
68
+ effective_page_size = max_items
69
+ session = AsanaSession.from_env(paginate=fetch_all, page_size=effective_page_size)
50
70
  api = CustomFieldSettingsApi(session.client)
51
71
  opts: dict[str, Any] = {}
52
- if limit is not None:
53
- opts["limit"] = limit
54
72
  if offset is not None:
55
73
  opts["offset"] = offset
56
74
  if opt_fields is not None:
57
75
  opts["opt_fields"] = opt_fields
76
+ if max_items is not None:
77
+ return session.fetch_capped(api.get_custom_field_settings_for_portfolio, portfolio, opts=opts, max_items=max_items)
58
78
  return api.get_custom_field_settings_for_portfolio(portfolio, opts)
59
79
 
60
80
 
61
81
  @custom_field_settings_group.command("get-custom-field-settings-for-project")
62
82
  @click.option("--project", required=True, help="Globally unique identifier for the project.")
63
- @click.option("--limit", type=int, default=None, help="Results per page. The number of objects to return per page. The value must be between 1 and 100.")
64
83
  @click.option("--offset", default=None, help="Offset token. An offset to the next page returned by the API. A pagination request will return an offset token, which can be used as an input parameter to the next request. If an offset is not pass...")
65
84
  @click.option("--opt-fields", default=None, help="This endpoint returns a resource which excludes some properties by default. To include those optional properties, set this query parameter to a comma-separated list of the properties you wish to in...")
66
- @click.option("--paginate", is_flag=True, default=False, help="Fetch all pages")
85
+ @click.option("--all-items", "all_items", is_flag=True, default=False, help="Fetch all items (no cap)")
86
+ @click.option("--paginate", "paginate", is_flag=True, default=False, help="(Deprecated) Alias for --all-items")
87
+ @click.option("--page-size", "page_size", type=int, default=None, help="Items per page (Asana API requires 1-100, default 100)")
88
+ @click.option("--max-items", "max_items", type=int, default=None, help="Stop after fetching this many items in total")
67
89
  @formatted
68
- def get_custom_field_settings_for_project(project: str, limit: int | None, offset: str | None, opt_fields: str | None, paginate: bool) -> Any:
90
+ def get_custom_field_settings_for_project(project: str, offset: str | None, opt_fields: str | None, all_items: bool, paginate: bool, page_size: int | None, max_items: int | None) -> Any:
69
91
  """Get a project's custom fields"""
70
- session = AsanaSession.from_env(paginate=paginate)
92
+ if paginate:
93
+ click.echo("Warning: --paginate is deprecated; use --all-items instead.", err=True)
94
+ fetch_all = all_items or paginate
95
+ if fetch_all and max_items is not None:
96
+ raise click.UsageError("--max-items cannot be combined with --all-items (or its deprecated alias --paginate)")
97
+ effective_page_size = page_size
98
+ if max_items is not None and (page_size is None or page_size > max_items):
99
+ effective_page_size = max_items
100
+ session = AsanaSession.from_env(paginate=fetch_all, page_size=effective_page_size)
71
101
  api = CustomFieldSettingsApi(session.client)
72
102
  opts: dict[str, Any] = {}
73
- if limit is not None:
74
- opts["limit"] = limit
75
103
  if offset is not None:
76
104
  opts["offset"] = offset
77
105
  if opt_fields is not None:
78
106
  opts["opt_fields"] = opt_fields
107
+ if max_items is not None:
108
+ return session.fetch_capped(api.get_custom_field_settings_for_project, project, opts=opts, max_items=max_items)
79
109
  return api.get_custom_field_settings_for_project(project, opts)
80
110
 
81
111
 
@@ -72,23 +72,33 @@ def get_custom_field(custom_field: str, opt_fields: str | None) -> Any:
72
72
 
73
73
  @custom_fields_group.command("get-custom-fields-for-workspace")
74
74
  @click.option("--workspace", default=None, help="Workspace GID (falls back to ASANA_DEFAULT_WORKSPACE)")
75
- @click.option("--limit", type=int, default=None, help="Results per page. The number of objects to return per page. The value must be between 1 and 100.")
76
75
  @click.option("--offset", default=None, help="Offset token. An offset to the next page returned by the API. A pagination request will return an offset token, which can be used as an input parameter to the next request. If an offset is not pass...")
77
76
  @click.option("--opt-fields", default=None, help="This endpoint returns a resource which excludes some properties by default. To include those optional properties, set this query parameter to a comma-separated list of the properties you wish to in...")
78
- @click.option("--paginate", is_flag=True, default=False, help="Fetch all pages")
77
+ @click.option("--all-items", "all_items", is_flag=True, default=False, help="Fetch all items (no cap)")
78
+ @click.option("--paginate", "paginate", is_flag=True, default=False, help="(Deprecated) Alias for --all-items")
79
+ @click.option("--page-size", "page_size", type=int, default=None, help="Items per page (Asana API requires 1-100, default 100)")
80
+ @click.option("--max-items", "max_items", type=int, default=None, help="Stop after fetching this many items in total")
79
81
  @formatted
80
- def get_custom_fields_for_workspace(workspace: str | None, limit: int | None, offset: str | None, opt_fields: str | None, paginate: bool) -> Any:
82
+ def get_custom_fields_for_workspace(workspace: str | None, offset: str | None, opt_fields: str | None, all_items: bool, paginate: bool, page_size: int | None, max_items: int | None) -> Any:
81
83
  """Get a workspace's custom fields"""
82
84
  resolved_workspace = resolve_workspace(workspace, required=True)
83
- session = AsanaSession.from_env(paginate=paginate)
85
+ if paginate:
86
+ click.echo("Warning: --paginate is deprecated; use --all-items instead.", err=True)
87
+ fetch_all = all_items or paginate
88
+ if fetch_all and max_items is not None:
89
+ raise click.UsageError("--max-items cannot be combined with --all-items (or its deprecated alias --paginate)")
90
+ effective_page_size = page_size
91
+ if max_items is not None and (page_size is None or page_size > max_items):
92
+ effective_page_size = max_items
93
+ session = AsanaSession.from_env(paginate=fetch_all, page_size=effective_page_size)
84
94
  api = CustomFieldsApi(session.client)
85
95
  opts: dict[str, Any] = {}
86
- if limit is not None:
87
- opts["limit"] = limit
88
96
  if offset is not None:
89
97
  opts["offset"] = offset
90
98
  if opt_fields is not None:
91
99
  opts["opt_fields"] = opt_fields
100
+ if max_items is not None:
101
+ return session.fetch_capped(api.get_custom_fields_for_workspace, resolved_workspace, opts=opts, max_items=max_items)
92
102
  return api.get_custom_fields_for_workspace(resolved_workspace, opts)
93
103
 
94
104
 
@@ -32,20 +32,30 @@ def get_custom_type(custom_type: str, opt_fields: str | None) -> Any:
32
32
 
33
33
  @custom_types_group.command("get-custom-types")
34
34
  @click.option("--project", required=True, help="Globally unique identifier for the project, which is used as a filter when retrieving all custom types.")
35
- @click.option("--limit", type=int, default=None, help="Results per page. The number of objects to return per page. The value must be between 1 and 100.")
36
35
  @click.option("--offset", default=None, help="Offset token. An offset to the next page returned by the API. A pagination request will return an offset token, which can be used as an input parameter to the next request. If an offset is not pass...")
37
36
  @click.option("--opt-fields", default=None, help="This endpoint returns a resource which excludes some properties by default. To include those optional properties, set this query parameter to a comma-separated list of the properties you wish to in...")
38
- @click.option("--paginate", is_flag=True, default=False, help="Fetch all pages")
37
+ @click.option("--all-items", "all_items", is_flag=True, default=False, help="Fetch all items (no cap)")
38
+ @click.option("--paginate", "paginate", is_flag=True, default=False, help="(Deprecated) Alias for --all-items")
39
+ @click.option("--page-size", "page_size", type=int, default=None, help="Items per page (Asana API requires 1-100, default 100)")
40
+ @click.option("--max-items", "max_items", type=int, default=None, help="Stop after fetching this many items in total")
39
41
  @formatted
40
- def get_custom_types(project: str, limit: int | None, offset: str | None, opt_fields: str | None, paginate: bool) -> Any:
42
+ def get_custom_types(project: str, offset: str | None, opt_fields: str | None, all_items: bool, paginate: bool, page_size: int | None, max_items: int | None) -> Any:
41
43
  """Get all custom types associated with an object"""
42
- session = AsanaSession.from_env(paginate=paginate)
44
+ if paginate:
45
+ click.echo("Warning: --paginate is deprecated; use --all-items instead.", err=True)
46
+ fetch_all = all_items or paginate
47
+ if fetch_all and max_items is not None:
48
+ raise click.UsageError("--max-items cannot be combined with --all-items (or its deprecated alias --paginate)")
49
+ effective_page_size = page_size
50
+ if max_items is not None and (page_size is None or page_size > max_items):
51
+ effective_page_size = max_items
52
+ session = AsanaSession.from_env(paginate=fetch_all, page_size=effective_page_size)
43
53
  api = CustomTypesApi(session.client)
44
54
  opts: dict[str, Any] = {}
45
- if limit is not None:
46
- opts["limit"] = limit
47
55
  if offset is not None:
48
56
  opts["offset"] = offset
49
57
  if opt_fields is not None:
50
58
  opts["opt_fields"] = opt_fields
59
+ if max_items is not None:
60
+ return session.fetch_capped(api.get_custom_types, project, opts=opts, max_items=max_items)
51
61
  return api.get_custom_types(project, opts)
@@ -48,25 +48,35 @@ def get_goal_relationship(goal_relationship: str, opt_fields: str | None) -> Any
48
48
 
49
49
  @goal_relationships_group.command("get-goal-relationships")
50
50
  @click.option("--supported-goal", required=True, help="Globally unique identifier for the supported goal in the goal relationship.")
51
- @click.option("--limit", type=int, default=None, help="Results per page. The number of objects to return per page. The value must be between 1 and 100.")
52
51
  @click.option("--offset", default=None, help="Offset token. An offset to the next page returned by the API. A pagination request will return an offset token, which can be used as an input parameter to the next request. If an offset is not pass...")
53
52
  @click.option("--opt-fields", default=None, help="This endpoint returns a resource which excludes some properties by default. To include those optional properties, set this query parameter to a comma-separated list of the properties you wish to in...")
54
53
  @click.option("--resource-subtype", default=None, help="If provided, filter to goal relationships with a given resource_subtype.")
55
- @click.option("--paginate", is_flag=True, default=False, help="Fetch all pages")
54
+ @click.option("--all-items", "all_items", is_flag=True, default=False, help="Fetch all items (no cap)")
55
+ @click.option("--paginate", "paginate", is_flag=True, default=False, help="(Deprecated) Alias for --all-items")
56
+ @click.option("--page-size", "page_size", type=int, default=None, help="Items per page (Asana API requires 1-100, default 100)")
57
+ @click.option("--max-items", "max_items", type=int, default=None, help="Stop after fetching this many items in total")
56
58
  @formatted
57
- def get_goal_relationships(supported_goal: str, limit: int | None, offset: str | None, opt_fields: str | None, resource_subtype: str | None, paginate: bool) -> Any:
59
+ def get_goal_relationships(supported_goal: str, offset: str | None, opt_fields: str | None, resource_subtype: str | None, all_items: bool, paginate: bool, page_size: int | None, max_items: int | None) -> Any:
58
60
  """Get goal relationships"""
59
- session = AsanaSession.from_env(paginate=paginate)
61
+ if paginate:
62
+ click.echo("Warning: --paginate is deprecated; use --all-items instead.", err=True)
63
+ fetch_all = all_items or paginate
64
+ if fetch_all and max_items is not None:
65
+ raise click.UsageError("--max-items cannot be combined with --all-items (or its deprecated alias --paginate)")
66
+ effective_page_size = page_size
67
+ if max_items is not None and (page_size is None or page_size > max_items):
68
+ effective_page_size = max_items
69
+ session = AsanaSession.from_env(paginate=fetch_all, page_size=effective_page_size)
60
70
  api = GoalRelationshipsApi(session.client)
61
71
  opts: dict[str, Any] = {}
62
- if limit is not None:
63
- opts["limit"] = limit
64
72
  if offset is not None:
65
73
  opts["offset"] = offset
66
74
  if opt_fields is not None:
67
75
  opts["opt_fields"] = opt_fields
68
76
  if resource_subtype is not None:
69
77
  opts["resource_subtype"] = resource_subtype
78
+ if max_items is not None:
79
+ return session.fetch_capped(api.get_goal_relationships, supported_goal, opts=opts, max_items=max_items)
70
80
  return api.get_goal_relationships(supported_goal, opts)
71
81
 
72
82