google-analytics-cli 0.1.0__py3-none-any.whl
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.
- ga_cli/__init__.py +8 -0
- ga_cli/api/__init__.py +0 -0
- ga_cli/api/client.py +142 -0
- ga_cli/auth/__init__.py +35 -0
- ga_cli/auth/credentials.py +126 -0
- ga_cli/auth/oauth.py +322 -0
- ga_cli/auth/service_account.py +155 -0
- ga_cli/commands/__init__.py +0 -0
- ga_cli/commands/access_bindings.py +254 -0
- ga_cli/commands/access_reports.py +201 -0
- ga_cli/commands/account_summaries.py +68 -0
- ga_cli/commands/accounts.py +297 -0
- ga_cli/commands/agent_cmd.py +776 -0
- ga_cli/commands/annotations.py +264 -0
- ga_cli/commands/audiences.py +223 -0
- ga_cli/commands/auth_cmd.py +205 -0
- ga_cli/commands/bigquery_links.py +309 -0
- ga_cli/commands/calculated_metrics.py +312 -0
- ga_cli/commands/channel_groups.py +223 -0
- ga_cli/commands/completions_cmd.py +55 -0
- ga_cli/commands/config_cmd.py +113 -0
- ga_cli/commands/custom_dimensions.py +272 -0
- ga_cli/commands/custom_metrics.py +305 -0
- ga_cli/commands/data_retention.py +153 -0
- ga_cli/commands/data_streams.py +277 -0
- ga_cli/commands/event_create_rules.py +250 -0
- ga_cli/commands/event_edit_rules.py +292 -0
- ga_cli/commands/firebase_links.py +142 -0
- ga_cli/commands/google_ads_links.py +225 -0
- ga_cli/commands/key_events.py +269 -0
- ga_cli/commands/mp_secrets.py +265 -0
- ga_cli/commands/properties.py +330 -0
- ga_cli/commands/property_settings.py +287 -0
- ga_cli/commands/reports.py +726 -0
- ga_cli/commands/upgrade_cmd.py +148 -0
- ga_cli/config/__init__.py +0 -0
- ga_cli/config/constants.py +61 -0
- ga_cli/config/store.py +115 -0
- ga_cli/main.py +110 -0
- ga_cli/utils/__init__.py +20 -0
- ga_cli/utils/describe.py +129 -0
- ga_cli/utils/dry_run.py +40 -0
- ga_cli/utils/errors.py +150 -0
- ga_cli/utils/output.py +209 -0
- ga_cli/utils/pagination.py +93 -0
- google_analytics_cli-0.1.0.dist-info/METADATA +321 -0
- google_analytics_cli-0.1.0.dist-info/RECORD +49 -0
- google_analytics_cli-0.1.0.dist-info/WHEEL +4 -0
- google_analytics_cli-0.1.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
"""Custom metric management commands."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
import questionary
|
|
6
|
+
import typer
|
|
7
|
+
|
|
8
|
+
from ..api.client import get_admin_client
|
|
9
|
+
from ..config.store import get_effective_value
|
|
10
|
+
from ..utils import (
|
|
11
|
+
handle_dry_run,
|
|
12
|
+
handle_error,
|
|
13
|
+
info,
|
|
14
|
+
output,
|
|
15
|
+
require_options,
|
|
16
|
+
resolve_output_format,
|
|
17
|
+
success,
|
|
18
|
+
)
|
|
19
|
+
from ..utils.pagination import paginate_all
|
|
20
|
+
|
|
21
|
+
custom_metrics_app = typer.Typer(
|
|
22
|
+
name="custom-metrics",
|
|
23
|
+
help="Manage custom metrics",
|
|
24
|
+
no_args_is_help=True,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
_VALID_SCOPES = ("EVENT",)
|
|
28
|
+
_VALID_MEASUREMENT_UNITS = (
|
|
29
|
+
"STANDARD",
|
|
30
|
+
"CURRENCY",
|
|
31
|
+
"FEET",
|
|
32
|
+
"METERS",
|
|
33
|
+
"KILOMETERS",
|
|
34
|
+
"MILES",
|
|
35
|
+
"MILLISECONDS",
|
|
36
|
+
"SECONDS",
|
|
37
|
+
"MINUTES",
|
|
38
|
+
"HOURS",
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@custom_metrics_app.command("list")
|
|
43
|
+
def list_cmd(
|
|
44
|
+
property_id: Optional[str] = typer.Option(
|
|
45
|
+
None, "--property-id", "-p", help="Property ID (numeric)"
|
|
46
|
+
),
|
|
47
|
+
output_format: Optional[str] = typer.Option(
|
|
48
|
+
None, "--output", "-o", help="Output format (json, table, compact)"
|
|
49
|
+
),
|
|
50
|
+
):
|
|
51
|
+
"""List custom metrics for a property."""
|
|
52
|
+
try:
|
|
53
|
+
effective_property = get_effective_value(property_id, "default_property_id")
|
|
54
|
+
require_options({"property_id": effective_property}, ["property_id"])
|
|
55
|
+
effective_format = resolve_output_format(output_format)
|
|
56
|
+
|
|
57
|
+
admin = get_admin_client()
|
|
58
|
+
metrics = paginate_all(
|
|
59
|
+
lambda **kw: admin.properties()
|
|
60
|
+
.customMetrics()
|
|
61
|
+
.list(parent=f"properties/{effective_property}", **kw)
|
|
62
|
+
.execute(),
|
|
63
|
+
"customMetrics",
|
|
64
|
+
pageSize=200,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
output(
|
|
68
|
+
metrics,
|
|
69
|
+
effective_format,
|
|
70
|
+
columns=[
|
|
71
|
+
"name",
|
|
72
|
+
"parameterName",
|
|
73
|
+
"displayName",
|
|
74
|
+
"scope",
|
|
75
|
+
"measurementUnit",
|
|
76
|
+
"description",
|
|
77
|
+
],
|
|
78
|
+
headers=[
|
|
79
|
+
"Resource Name",
|
|
80
|
+
"Parameter Name",
|
|
81
|
+
"Display Name",
|
|
82
|
+
"Scope",
|
|
83
|
+
"Measurement Unit",
|
|
84
|
+
"Description",
|
|
85
|
+
],
|
|
86
|
+
)
|
|
87
|
+
except Exception as e:
|
|
88
|
+
handle_error(e)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@custom_metrics_app.command("get")
|
|
92
|
+
def get_cmd(
|
|
93
|
+
property_id: Optional[str] = typer.Option(
|
|
94
|
+
None, "--property-id", "-p", help="Property ID (numeric)"
|
|
95
|
+
),
|
|
96
|
+
metric_id: str = typer.Option(
|
|
97
|
+
..., "--metric-id", "-m", help="Custom metric ID"
|
|
98
|
+
),
|
|
99
|
+
output_format: Optional[str] = typer.Option(
|
|
100
|
+
None, "--output", "-o", help="Output format (json, table, compact)"
|
|
101
|
+
),
|
|
102
|
+
):
|
|
103
|
+
"""Get details for a custom metric."""
|
|
104
|
+
try:
|
|
105
|
+
effective_property = get_effective_value(property_id, "default_property_id")
|
|
106
|
+
require_options({"property_id": effective_property}, ["property_id"])
|
|
107
|
+
effective_format = resolve_output_format(output_format)
|
|
108
|
+
|
|
109
|
+
admin = get_admin_client()
|
|
110
|
+
metric = (
|
|
111
|
+
admin.properties()
|
|
112
|
+
.customMetrics()
|
|
113
|
+
.get(name=f"properties/{effective_property}/customMetrics/{metric_id}")
|
|
114
|
+
.execute()
|
|
115
|
+
)
|
|
116
|
+
output(metric, effective_format)
|
|
117
|
+
except Exception as e:
|
|
118
|
+
handle_error(e)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@custom_metrics_app.command("create")
|
|
122
|
+
def create_cmd(
|
|
123
|
+
property_id: Optional[str] = typer.Option(
|
|
124
|
+
None, "--property-id", "-p", help="Property ID (numeric)"
|
|
125
|
+
),
|
|
126
|
+
parameter_name: str = typer.Option(
|
|
127
|
+
..., "--parameter-name", help="Event parameter name"
|
|
128
|
+
),
|
|
129
|
+
display_name: str = typer.Option(..., "--display-name", help="Display name in GA4 UI"),
|
|
130
|
+
scope: str = typer.Option(..., "--scope", help="Scope: EVENT"),
|
|
131
|
+
measurement_unit: str = typer.Option(
|
|
132
|
+
...,
|
|
133
|
+
"--measurement-unit",
|
|
134
|
+
help="Unit: STANDARD, CURRENCY, FEET, METERS, KILOMETERS, "
|
|
135
|
+
"MILES, MILLISECONDS, SECONDS, MINUTES, HOURS",
|
|
136
|
+
),
|
|
137
|
+
description: str = typer.Option("", "--description", help="Description"),
|
|
138
|
+
dry_run: bool = typer.Option(
|
|
139
|
+
False, "--dry-run", help="Preview the request without executing"
|
|
140
|
+
),
|
|
141
|
+
output_format: Optional[str] = typer.Option(
|
|
142
|
+
None, "--output", "-o", help="Output format (json, table, compact)"
|
|
143
|
+
),
|
|
144
|
+
):
|
|
145
|
+
"""Create a custom metric."""
|
|
146
|
+
try:
|
|
147
|
+
effective_property = get_effective_value(property_id, "default_property_id")
|
|
148
|
+
require_options({"property_id": effective_property}, ["property_id"])
|
|
149
|
+
effective_format = resolve_output_format(output_format)
|
|
150
|
+
|
|
151
|
+
scope_upper = scope.upper()
|
|
152
|
+
if scope_upper not in _VALID_SCOPES:
|
|
153
|
+
raise typer.BadParameter(
|
|
154
|
+
f"Invalid scope '{scope}'. Must be one of: {', '.join(_VALID_SCOPES)}"
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
unit_upper = measurement_unit.upper()
|
|
158
|
+
if unit_upper not in _VALID_MEASUREMENT_UNITS:
|
|
159
|
+
raise typer.BadParameter(
|
|
160
|
+
f"Invalid measurement unit '{measurement_unit}'. "
|
|
161
|
+
f"Must be one of: {', '.join(_VALID_MEASUREMENT_UNITS)}"
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
body = {
|
|
165
|
+
"parameterName": parameter_name,
|
|
166
|
+
"displayName": display_name,
|
|
167
|
+
"scope": scope_upper,
|
|
168
|
+
"measurementUnit": unit_upper,
|
|
169
|
+
"description": description,
|
|
170
|
+
}
|
|
171
|
+
if dry_run:
|
|
172
|
+
handle_dry_run("create", "POST", f"properties/{effective_property}", body)
|
|
173
|
+
|
|
174
|
+
admin = get_admin_client()
|
|
175
|
+
metric = (
|
|
176
|
+
admin.properties()
|
|
177
|
+
.customMetrics()
|
|
178
|
+
.create(parent=f"properties/{effective_property}", body=body)
|
|
179
|
+
.execute()
|
|
180
|
+
)
|
|
181
|
+
output(metric, effective_format)
|
|
182
|
+
except (typer.BadParameter, typer.Exit):
|
|
183
|
+
raise
|
|
184
|
+
except Exception as e:
|
|
185
|
+
handle_error(e)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
@custom_metrics_app.command("update")
|
|
189
|
+
def update_cmd(
|
|
190
|
+
property_id: Optional[str] = typer.Option(
|
|
191
|
+
None, "--property-id", "-p", help="Property ID (numeric)"
|
|
192
|
+
),
|
|
193
|
+
metric_id: str = typer.Option(
|
|
194
|
+
..., "--metric-id", "-m", help="Custom metric ID"
|
|
195
|
+
),
|
|
196
|
+
display_name: Optional[str] = typer.Option(None, "--display-name", help="New display name"),
|
|
197
|
+
description: Optional[str] = typer.Option(None, "--description", help="New description"),
|
|
198
|
+
measurement_unit: Optional[str] = typer.Option(
|
|
199
|
+
None, "--measurement-unit", help="New measurement unit"
|
|
200
|
+
),
|
|
201
|
+
dry_run: bool = typer.Option(
|
|
202
|
+
False, "--dry-run", help="Preview the request without executing"
|
|
203
|
+
),
|
|
204
|
+
output_format: Optional[str] = typer.Option(
|
|
205
|
+
None, "--output", "-o", help="Output format (json, table, compact)"
|
|
206
|
+
),
|
|
207
|
+
):
|
|
208
|
+
"""Update a custom metric."""
|
|
209
|
+
try:
|
|
210
|
+
effective_property = get_effective_value(property_id, "default_property_id")
|
|
211
|
+
require_options({"property_id": effective_property}, ["property_id"])
|
|
212
|
+
effective_format = resolve_output_format(output_format)
|
|
213
|
+
|
|
214
|
+
body = {}
|
|
215
|
+
mask_fields = []
|
|
216
|
+
if display_name is not None:
|
|
217
|
+
body["displayName"] = display_name
|
|
218
|
+
mask_fields.append("displayName")
|
|
219
|
+
if description is not None:
|
|
220
|
+
body["description"] = description
|
|
221
|
+
mask_fields.append("description")
|
|
222
|
+
if measurement_unit is not None:
|
|
223
|
+
unit_upper = measurement_unit.upper()
|
|
224
|
+
if unit_upper not in _VALID_MEASUREMENT_UNITS:
|
|
225
|
+
raise typer.BadParameter(
|
|
226
|
+
f"Invalid measurement unit '{measurement_unit}'. "
|
|
227
|
+
f"Must be one of: {', '.join(_VALID_MEASUREMENT_UNITS)}"
|
|
228
|
+
)
|
|
229
|
+
body["measurementUnit"] = unit_upper
|
|
230
|
+
mask_fields.append("measurementUnit")
|
|
231
|
+
|
|
232
|
+
if not mask_fields:
|
|
233
|
+
raise typer.BadParameter(
|
|
234
|
+
"At least one field must be specified: "
|
|
235
|
+
"--display-name, --description, --measurement-unit"
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
resource_name = f"properties/{effective_property}/customMetrics/{metric_id}"
|
|
239
|
+
if dry_run:
|
|
240
|
+
handle_dry_run(
|
|
241
|
+
"update", "PATCH", resource_name,
|
|
242
|
+
body, update_mask=",".join(mask_fields),
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
admin = get_admin_client()
|
|
246
|
+
metric = (
|
|
247
|
+
admin.properties()
|
|
248
|
+
.customMetrics()
|
|
249
|
+
.patch(
|
|
250
|
+
name=resource_name,
|
|
251
|
+
body=body,
|
|
252
|
+
updateMask=",".join(mask_fields),
|
|
253
|
+
)
|
|
254
|
+
.execute()
|
|
255
|
+
)
|
|
256
|
+
output(metric, effective_format)
|
|
257
|
+
except (typer.BadParameter, typer.Exit):
|
|
258
|
+
raise
|
|
259
|
+
except Exception as e:
|
|
260
|
+
handle_error(e)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
@custom_metrics_app.command("archive")
|
|
264
|
+
def archive_cmd(
|
|
265
|
+
property_id: Optional[str] = typer.Option(
|
|
266
|
+
None, "--property-id", "-p", help="Property ID (numeric)"
|
|
267
|
+
),
|
|
268
|
+
metric_id: str = typer.Option(
|
|
269
|
+
..., "--metric-id", "-m", help="Custom metric ID"
|
|
270
|
+
),
|
|
271
|
+
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt"),
|
|
272
|
+
dry_run: bool = typer.Option(
|
|
273
|
+
False, "--dry-run", help="Preview the request without executing"
|
|
274
|
+
),
|
|
275
|
+
):
|
|
276
|
+
"""Archive a custom metric."""
|
|
277
|
+
try:
|
|
278
|
+
effective_property = get_effective_value(property_id, "default_property_id")
|
|
279
|
+
require_options({"property_id": effective_property}, ["property_id"])
|
|
280
|
+
|
|
281
|
+
if dry_run:
|
|
282
|
+
handle_dry_run(
|
|
283
|
+
"archive", "POST",
|
|
284
|
+
f"properties/{effective_property}/customMetrics/{metric_id}",
|
|
285
|
+
None,
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
if not yes:
|
|
289
|
+
confirmed = questionary.confirm(
|
|
290
|
+
f"Archive custom metric {metric_id}? This cannot be undone."
|
|
291
|
+
).ask()
|
|
292
|
+
if not confirmed:
|
|
293
|
+
info("Cancelled.")
|
|
294
|
+
raise typer.Exit()
|
|
295
|
+
|
|
296
|
+
admin = get_admin_client()
|
|
297
|
+
resource_name = f"properties/{effective_property}/customMetrics/{metric_id}"
|
|
298
|
+
admin.properties().customMetrics().archive(
|
|
299
|
+
name=resource_name, body={}
|
|
300
|
+
).execute()
|
|
301
|
+
success(f"Custom metric {metric_id} archived.")
|
|
302
|
+
except typer.Exit:
|
|
303
|
+
raise
|
|
304
|
+
except Exception as e:
|
|
305
|
+
handle_error(e)
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""Data retention settings commands."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from ..api.client import get_admin_client
|
|
8
|
+
from ..config.store import get_effective_value
|
|
9
|
+
from ..utils import (
|
|
10
|
+
handle_dry_run,
|
|
11
|
+
handle_error,
|
|
12
|
+
output,
|
|
13
|
+
require_options,
|
|
14
|
+
resolve_output_format,
|
|
15
|
+
success,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
data_retention_app = typer.Typer(
|
|
19
|
+
name="data-retention",
|
|
20
|
+
help="Manage data retention settings for a property",
|
|
21
|
+
no_args_is_help=True,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
_RETENTION_CHOICES = [
|
|
25
|
+
"TWO_MONTHS",
|
|
26
|
+
"FOURTEEN_MONTHS",
|
|
27
|
+
"TWENTY_SIX_MONTHS",
|
|
28
|
+
"THIRTY_EIGHT_MONTHS",
|
|
29
|
+
"FIFTY_MONTHS",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@data_retention_app.command("get")
|
|
34
|
+
def get_cmd(
|
|
35
|
+
property_id: Optional[str] = typer.Option(
|
|
36
|
+
None, "--property-id", "-p", help="Property ID (numeric)"
|
|
37
|
+
),
|
|
38
|
+
output_format: Optional[str] = typer.Option(
|
|
39
|
+
None, "--output", "-o", help="Output format (json, table, compact)"
|
|
40
|
+
),
|
|
41
|
+
):
|
|
42
|
+
"""Get data retention settings for a property."""
|
|
43
|
+
try:
|
|
44
|
+
effective_property = get_effective_value(property_id, "default_property_id")
|
|
45
|
+
require_options({"property_id": effective_property}, ["property_id"])
|
|
46
|
+
effective_format = resolve_output_format(output_format)
|
|
47
|
+
|
|
48
|
+
admin = get_admin_client()
|
|
49
|
+
settings = (
|
|
50
|
+
admin.properties()
|
|
51
|
+
.getDataRetentionSettings(name=f"properties/{effective_property}/dataRetentionSettings")
|
|
52
|
+
.execute()
|
|
53
|
+
)
|
|
54
|
+
output(
|
|
55
|
+
settings,
|
|
56
|
+
effective_format,
|
|
57
|
+
columns=[
|
|
58
|
+
"name",
|
|
59
|
+
"eventDataRetention",
|
|
60
|
+
"userDataRetention",
|
|
61
|
+
"resetUserDataOnNewActivity",
|
|
62
|
+
],
|
|
63
|
+
headers=[
|
|
64
|
+
"Resource Name",
|
|
65
|
+
"Event Data Retention",
|
|
66
|
+
"User Data Retention",
|
|
67
|
+
"Reset on New Activity",
|
|
68
|
+
],
|
|
69
|
+
)
|
|
70
|
+
except Exception as e:
|
|
71
|
+
handle_error(e)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@data_retention_app.command("update")
|
|
75
|
+
def update_cmd(
|
|
76
|
+
property_id: Optional[str] = typer.Option(
|
|
77
|
+
None, "--property-id", "-p", help="Property ID (numeric)"
|
|
78
|
+
),
|
|
79
|
+
event_data_retention: Optional[str] = typer.Option(
|
|
80
|
+
None,
|
|
81
|
+
"--event-data-retention",
|
|
82
|
+
help=f"Event data retention period ({', '.join(_RETENTION_CHOICES)})",
|
|
83
|
+
),
|
|
84
|
+
user_data_retention: Optional[str] = typer.Option(
|
|
85
|
+
None,
|
|
86
|
+
"--user-data-retention",
|
|
87
|
+
help=f"User data retention period ({', '.join(_RETENTION_CHOICES)})",
|
|
88
|
+
),
|
|
89
|
+
reset_on_new_activity: Optional[bool] = typer.Option(
|
|
90
|
+
None,
|
|
91
|
+
"--reset-on-new-activity/--no-reset-on-new-activity",
|
|
92
|
+
help="Reset user data retention on new activity",
|
|
93
|
+
),
|
|
94
|
+
dry_run: bool = typer.Option(
|
|
95
|
+
False, "--dry-run", help="Preview the request without executing"
|
|
96
|
+
),
|
|
97
|
+
output_format: Optional[str] = typer.Option(
|
|
98
|
+
None, "--output", "-o", help="Output format (json, table, compact)"
|
|
99
|
+
),
|
|
100
|
+
):
|
|
101
|
+
"""Update data retention settings for a property."""
|
|
102
|
+
try:
|
|
103
|
+
effective_property = get_effective_value(property_id, "default_property_id")
|
|
104
|
+
require_options({"property_id": effective_property}, ["property_id"])
|
|
105
|
+
effective_format = resolve_output_format(output_format)
|
|
106
|
+
|
|
107
|
+
field_map = {
|
|
108
|
+
"eventDataRetention": event_data_retention,
|
|
109
|
+
"userDataRetention": user_data_retention,
|
|
110
|
+
"resetUserDataOnNewActivity": reset_on_new_activity,
|
|
111
|
+
}
|
|
112
|
+
body = {k: v for k, v in field_map.items() if v is not None}
|
|
113
|
+
|
|
114
|
+
if not body:
|
|
115
|
+
raise typer.BadParameter(
|
|
116
|
+
"At least one of --event-data-retention, --user-data-retention, "
|
|
117
|
+
"or --reset-on-new-activity must be specified."
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Validate retention values
|
|
121
|
+
for key in ("eventDataRetention", "userDataRetention"):
|
|
122
|
+
val = body.get(key)
|
|
123
|
+
if val and val not in _RETENTION_CHOICES:
|
|
124
|
+
raise typer.BadParameter(
|
|
125
|
+
f"Invalid value '{val}' for {key}. "
|
|
126
|
+
f"Must be one of: {', '.join(_RETENTION_CHOICES)}"
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
update_mask = ",".join(body.keys())
|
|
130
|
+
|
|
131
|
+
if dry_run:
|
|
132
|
+
handle_dry_run(
|
|
133
|
+
"update", "PATCH",
|
|
134
|
+
f"properties/{effective_property}/dataRetentionSettings",
|
|
135
|
+
body, update_mask=update_mask,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
admin = get_admin_client()
|
|
139
|
+
settings = (
|
|
140
|
+
admin.properties()
|
|
141
|
+
.updateDataRetentionSettings(
|
|
142
|
+
name=f"properties/{effective_property}/dataRetentionSettings",
|
|
143
|
+
updateMask=update_mask,
|
|
144
|
+
body=body,
|
|
145
|
+
)
|
|
146
|
+
.execute()
|
|
147
|
+
)
|
|
148
|
+
success("Data retention settings updated.")
|
|
149
|
+
output(settings, effective_format)
|
|
150
|
+
except (typer.BadParameter, typer.Exit):
|
|
151
|
+
raise
|
|
152
|
+
except Exception as e:
|
|
153
|
+
handle_error(e)
|