Two updates

Fixed bug in `gam <UserTypeEntity> create contact <JSONData>` that caused a trap when
contacts were being copied from one user to another.

Updated the commands to allow specification of a task list by its title.
This commit is contained in:
Ross Scroggs
2023-10-19 08:14:03 -07:00
parent 7e9207ae3c
commit 55298f0134
4 changed files with 154 additions and 80 deletions

View File

@@ -1,24 +1,18 @@
- [Introduction](#introduction)
- [Requirements](#requirements)
- [Installation - First time GAM installation](#installation---first-time-GAM-installation)
- [Installation - Upgrading from a GAM version other than a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3](#installation---upgrading-from-a-gam-version-other-than-a-prior-version-of-gamadv-x-or-gamadv-xtd-or-gamadv-xtd3)
- [Installation - Upgrading from a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3](#installation---upgrading-from-a-prior-version-of-gamadv-x-or-gamadv-xtd-or-gamadv-xtd3)
# Introduction
GAMADV-XTD3 is a free, open source command line tool for Google Workspace Administrators to manage domain and user settings quickly and easily.
GAMADV-XTD3 is a free, open source command line tool for Google Workspace (formerly G Suite) Administrators to manage domain and user settings quickly and easily.
GAMADV-XTD3 is built with Python 3; as Python 2 support ends on 2020-01-01, this is the version of Advanced GAM that new/existing users should install.
GAMADV-XTD3 is built with Python 3.
This page provides simple instructions for downloading, installing and starting to use GAMADV-XTD3.
GAMADV-XTD3 requires paid, or Education/Non-profit, editions of Google Workspace. G Suite Legacy Free Edition has limited API support and not all GAM commands work.
GAMADV-XTD3 runs on all versions of Google Workspace; Google Apps Free Edition has limited API support and not all GAM commands work.
GAMADV-XTD3 is a rewrite/extension of Jay Lee's [GAM], without his efforts, this version wouldn't exist.
GAMADV-XTD3 is backwards compatible with [GAM], meaning that if your command works with regular GAM, it will also work with GAMADV-XTD3. There may be differences in output, but the syntax is compatible.
# Documentation
Basic GAM documentation is hosted in the [GitHub Wiki]. Documentation specifically for GAMADV-XTD3 is hosted in the [GitHub GAMADV-XTD3 Wiki] and in Gam*.txt files.
Documentation for GAMADV-XTD3 is hosted in the [GitHub GAMADV-XTD3 Wiki] and in Gam*.txt files.
# Mailing List / Discussion group
The GAM mailing list / discussion group is hosted on [Google Groups]. You can join the list and interact via email, or just post from the web itself.
@@ -32,39 +26,48 @@ GAMADV-XTD3 is maintained by <a href="mailto:ross.scroggs@gmail.com">Ross Scrogg
# Requirements
To run all commands properly, GAMADV-XTD3 requires three things:
* An API project which identifies your install of GAMADV-XTD3 to Google and keeps track of API quotas.
* Authorization to act as your Google Workspace Administrator in order to perform management functions like add users, modify group settings and membership and pull domain reports.
* Authorization to act as your G Suite Administrator in order to perform management functions like add users, modify group settings and membership and pull domain reports.
* A special service account that is authorized to act on behalf of your users in order to modify user-specific settings and data such as Drive files, Calendars and Gmail messages and settings like signatures.
# Installation - First time GAM installation
Use these steps if you have never used any version of GAM in your domain. They will create a GAM project
and all necessary authentications.
* Download: [Downloads](Downloads)
* Configuration: [GAM Configuration](gam.cfg)
* Install: [How to Install Advanced GAM](How-to-Install-Advanced-GAM)
| [Downloads] | [Configuration] | [Install] |
| :---: | :---: | :---: |
# Installation - Upgrading from a GAM version other than a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3
Use these steps if you have used any version of GAM in your domain. They will update your GAM project
# Installation - Update Advanced GAM
Use these steps to update your version of GAMADV-XTD3.
| [Downloads] | [Configuration] | [UpdateAdvanced] |
| :---: | :---: | :---: |
# Installation - Upgrading from Standard GAM
Use these steps if you have used any version of Standard GAM in your domain. They will update your GAM project
and all necessary authentications.
* Download: [Downloads](Downloads)
* Configuration: [GAM Configuration](gam.cfg)
* Upgrade: [How to Upgrade from Standard GAM](How-to-Upgrade-from-Standard-GAM)
| [Downloads] | [Configuration] | [UpgradeFromStandard] |
| :---: | :---: | :---: |
# Installation - Upgrading from a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3
Use these steps if you already use GAMADV-X or GAMADV-XTD or GAMADV-XTD3. The updates may tell you to update your GAM project
# Installation - Upgrading from a prior version of GAMADV-X or GAMADV-XTD
Use these steps if you already use GAMADV-X or GAMADV-XTD. The updates may tell you to update your GAM project
or authentications because new features have been included.
* Updates: [GAM Updates]
* Download: [Downloads](Downloads)
| [Updates] | [Downloads] | [UpgradeFromAdvanced] |
| :---: | :---: | :---: |
# Multiple Versions
You can install multiple versions of GAM and GAMADV-XTD3 in different parallel directories.
[GAM]: https://github.com/GAM-team/GAM
[GitHub Releases]: https://github.com/taers232c/GAMADV-XTD3/releases
[GitHub]: https://github.com/taers232c/GAMADV-XTD3/tree/master
[GitHub Wiki]: https://github.com/GAM-team/GAM/wiki/
[GitHub GAMADV-XTD3 Wiki]: https://github.com/taers232c/GAMADV-XTD3/wiki/
[GitHub GAMADV-XTD3 Wiki]: https://github.com/taers232c/GAMADV-XTD3/wiki
[Google Groups]: https://groups.google.com/group/google-apps-manager
[GAM Updates]: https://github.com/taers232c/GAMADV-XTD3/wiki/GamUpdates
[Downloads]: https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads
[Configuration]: https://github.com/taers232c/GAMADV-XTD3/wiki/gam.cfg
[Install]: https://github.com/taers232c/GAMADV-XTD3/wiki/How-to-Install-Advanced-GAM
[UpdateAdvanced]: https://github.com/taers232c/GAMADV-XTD3/wiki/How-to-Update-Advanced-GAM
[UpgradeFromStandard]: https://github.com/taers232c/GAMADV-XTD3/wiki/How-to-Upgrade-from-Standard-GAM
[Updates]: https://github.com/taers232c/GAMADV-XTD3/wiki/GAM-Updates
[UpgradeFromAdvanced]: https://github.com/taers232c/GAMADV-XTD3/wiki/How-to-Upgrade-from-GAMADV-X-or-GAMADV-XTD

View File

@@ -588,6 +588,7 @@ If an item contains spaces, it should be surrounded by ".
<TakeoutBucketName> ::= takeout-export-[a-f,0-9,-]*
<TaskID> ::= <String>
<TaskListID> ::= <String>
<TaskListTitle> ::= tltitle:<String>
<TasklistIDTaskID> ::= <TasklistID>/<TaskID>
<ThreadID> ::= <String>
<TimeZone> ::= <String>
@@ -720,6 +721,7 @@ If an item contains spaces, it should be surrounded by ".
<SharedDriveIDList> ::= "<SharedDriveID>(,<SharedDriveID>)*"
<StringList> ::= "<String>(,<String>)*"
<TasklistIDList> ::= "<TasklistID>(,<TasklistID>)*"
<TasklistTitleList> ::= "'<TasklistTitle>'(,'<TasklistTitle>')*"
<TasklistIDTaskIDList> ::= "<TasklistIDTaskID>(,<TasklistIDTaskID>)*"
<ThreadIDList> ::= "<ThreadID>(,<ThreadID>)*"
<TimeList> ::= "<Time>(,<Time>)*"
@@ -1161,8 +1163,8 @@ Specify a collection of items by directly specifying them; the item type is dete
<SiteACLScopeList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<SiteEntity> ::=
<SiteList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<TasklistIDEntity> ::=
<TasklistIDList> | <FileSelector> | <CSVFileSelector>
<TasklistEntity> ::=
<TasklistIDList> | <TaskListTitleList> | <FileSelector> | <CSVFileSelector>
<TasklistIDTaskIDEntity> ::=
<TasklistIDTaskIDList> | <FileSelector> | <CSVFileSelector>
<ThreadIDEntity> ::=
@@ -7393,7 +7395,7 @@ gam <UserTypeEntity> show profile
(status needsaction|completed)|
(due <Time>)
gam <UserTypeEntity> create task <TasklistIDEntity>
gam <UserTypeEntity> create task <TasklistEntity>
<TaskAttribute>* [parent <TaskID>] [previous <TaskID>]
[compact|formatjson|returnidonly]
gam <UserTypeEntity> update task <TasklistIDTaskIDEntity>
@@ -7406,14 +7408,14 @@ gam <UserTypeEntity> move task <TasklistIDTaskIDEntity>
gam <UserTypeEntity> info task <TasklistIDTaskIDEntity>
[compact|formatjson]
gam <UserTypeEntity> show tasks [tasklists <TasklistIDEntity>]
gam <UserTypeEntity> show tasks [tasklists <TasklistEntity>]
[completedmin <Time>] [completedmax <Time>]
[duemin <Time>] [duemax <Time>]
[updatedmin <Time>]
[showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall]
[orderby completed|due|updated]
[countsonly|compact|formatjson]
gam <UserTypeEntity> print tasks [tasklists <TasklistIDEntity>] [todrive <ToDriveAttribute>*]
gam <UserTypeEntity> print tasks [tasklists <TasklistEntity>] [todrive <ToDriveAttribute>*]
[completedmin <Time>] [completedmax <Time>]
[duemin <Time>] [duemax <Time>]
[updatedmin <Time>]
@@ -7427,13 +7429,13 @@ gam <UserTypeEntity> print tasks [tasklists <TasklistIDEntity>] [todrive <ToDriv
gam <UserTypeEntity> create tasklist
<TasklistAttribute>*
[returnidonly] [formatjson]
gam <UserTypeEntity> update tasklist <TasklistIDEntity>
gam <UserTypeEntity> update tasklist <TasklistEntity>
<TasklistAttribute>*
[formatjson]
gam <UserTypeEntity> delete tasklist <TasklistIDEntity>
gam <UserTypeEntity> clear tasklist <TasklistIDEntity>
gam <UserTypeEntity> delete tasklist <TasklistEntity>
gam <UserTypeEntity> clear tasklist <TasklistEntity>
gam <UserTypeEntity> info tasklist <TasklistIDEntity>
gam <UserTypeEntity> info tasklist <TasklistEntity>
[formatjson]
gam <UserTypeEntity> show tasklists
[countsonly|formatjson]

View File

@@ -1,3 +1,32 @@
7.00.00
Merged GAM-Team version
6.65.00
Fixed bug in `gam <UserTypeEntity> create contact <JSONData>` that caused a trap when
contacts were being copied from one user to another.
* See: https://github.com/taers232c/GAMADV-XTD3/wiki/Users-People-Contacts-Profiles#copy-user-contacts-to-another-user
Updated the following commands to allow specification of a task list by its title.
```
<TaskListTitle> ::= tltitle:<String>
<TasklistTitleList> ::= "'<TasklistTitle>'(,'<TasklistTitle>')*"
<TasklistEntity> ::=
<TasklistIDList> | <TaskListTitleList> | <FileSelector> | <CSVFileSelector>
gam <UserTypeEntity> create task <TasklistEntity>
gam <UserTypeEntity> show tasks [tasklists <TasklistEntity>]
gam <UserTypeEntity> print tasks [tasklists <TasklistEntity>]
gam <UserTypeEntity> update tasklist <TasklistEntity>
gam <UserTypeEntity> delete tasklist <TasklistEntity>
gam <UserTypeEntity> clear tasklist <TasklistEntity>
gam <UserTypeEntity> info tasklist <TasklistEntity>
```
* See: https://github.com/taers232c/GAMADV-XTD3/wiki/Users-Tasks#specifying-task-lists
6.64.16
Fixed bug in `gam <UserTypeEntity> create task <TasklistIDEntity>` that caused a trap
@@ -20,6 +49,7 @@ Added command to get chrome app details.
```
gam info appdetails android|chrome|web <AppID> [formatjson]
```
* See: https://github.com/taers232c/GAMADV-XTD3/wiki/Chrome-Installed-Apps
6.64.12
@@ -34,7 +64,7 @@ Added support for Google Workspace Labs license.
6.64.10
Fixed bug introduced in 6.64.09 that caused a trap when `gam redirect csv <FileName> multiprocess` was used.
Fixed bug introduced in 6.64.09 that caused a trap when `gam redirect csv <FileName> multiprocess` was used.
6.64.09
@@ -72,10 +102,6 @@ gam <UserTypeEntity> print events <UserCalendarEntity> [<EventEntity>]
gam <UserTypeEntity> update calattendees <UserCalendarEntity> <EventEntity>
```
7.00.00
Merged GAM-Team version
6.64.04
Updated `gam calendars <CalendarEntity> move events` and `gam <UserTypeEntity> move events <UserCalendarEntity>`

View File

@@ -20146,7 +20146,19 @@ class PeopleManager():
unknownArgumentExit()
contactGroupsLists[PEOPLE_REMOVE_GROUPS_LIST].append(getString(Cmd.OB_STRING))
elif fieldName == PEOPLE_JSON:
person.update(getJSON(['resourceName', 'etag', 'metadata', PEOPLE_COVER_PHOTOS, PEOPLE_PHOTOS, PEOPLE_UPDATE_TIME]))
jsonData = getJSON(['resourceName', 'etag', 'metadata', PEOPLE_COVER_PHOTOS, PEOPLE_PHOTOS, PEOPLE_UPDATE_TIME])
for membership in jsonData.pop('memberships', []):
contactGroupName = membership.get('contactGroupMembership', {}).get('contactGroupName', '')
if contactGroupName:
contactGroupsLists[PEOPLE_GROUPS_LIST].append(contactGroupName)
newClientData = []
for clientData in jsonData.pop('clientData', []):
if clientData['key'] not in {'ContactId', 'CtsContactHash'}:
newClientData.append({'key': clientData['key'], 'value': clientData['value']})
if newClientData:
person.setdefault(PEOPLE_CLIENT_DATA, [])
person[PEOPLE_CLIENT_DATA].extend(newClientData)
person.update(jsonData)
return (person, set(person.keys()), contactGroupsLists)
PEOPLE_GROUP_ARGUMENT_TO_PROPERTY_MAP = {
@@ -20195,7 +20207,9 @@ class PeopleManager():
contactGroup.setdefault(fieldName, [])
contactGroup[fieldName].append(entry)
elif fieldName == PEOPLE_JSON:
contactGroup.update(getJSON(['resourceName', 'etag', 'metadata', 'groupType', 'formattedName', 'memberResourceNames', 'memberCount']))
jsonData = getJSON(['resourceName', 'etag', 'metadata', 'formattedName', 'memberResourceNames', 'memberCount'])
if jsonData.get('groupType', '') != 'SYSTEM_CONTACT_GROUP':
contactGroup[PEOPLE_GROUP_NAME] = jsonData['name']
return (contactGroup, ','.join(contactGroup.keys()))
PEOPLE_DIRECTORY_SOURCES_CHOICE_MAP = {
@@ -21917,6 +21931,8 @@ def createUserPeopleContactGroup(users):
entityType = Ent.USER
parameters = {'csvPF': None, 'titles': ['User', 'resourceName'], 'addCSVData': {}, 'returnIdOnly': False}
body, _ = peopleManager.GetContactGroupFields(parameters)
if PEOPLE_GROUP_NAME not in body:
return
csvPF = parameters['csvPF']
addCSVData = parameters['addCSVData']
if addCSVData:
@@ -68998,6 +69014,33 @@ def deleteNotesACLs(users):
entityServiceNotApplicableWarning(Ent.USER, user, i, count)
break
def getTaskLists(svc, user, i, count):
try:
results = callGAPIpages(svc.tasklists(), 'list', 'items',
pageMessage=getPageMessageForWhom(),
throwReasons=GAPI.TASKLIST_THROW_REASONS,
maxResults=100)
except GAPI.notFound:
results = []
except (GAPI.badRequest, GAPI.invalid) as e:
entityActionFailedWarning([Ent.USER, user, Ent.TASKLIST, None], str(e), i, count)
results = None
except GAPI.serviceNotAvailable:
entityServiceNotApplicableWarning(Ent.USER, user, i, count)
results = None
return results
def getTaskListIDfromTitle(svc, userTasklists, title, user, i, count):
if userTasklists is None:
printGettingEntityItemForWhom(Ent.TASKLIST, user, i, count)
userTasklists = getTaskLists(svc, user, i, count)
if userTasklists is None:
return None, None
for userTasklist in userTasklists:
if userTasklist['title'] == title:
return userTasklists, userTasklist['id']
return userTasklists, None
TASK_SKIP_OBJECTS = ['selfLink']
TASK_TIME_OBJECTS = ['due', 'completed', 'updated']
@@ -69048,7 +69091,7 @@ def getTaskMoveAttribute(myarg, kwargs):
return False
return True
# gam <UserTypeEntity> create task <TasklistIDEntity>
# gam <UserTypeEntity> create task <TasklistEntity>
# <TaskAttribute>* [parent <TaskID>] [previous <TaskID>]
# [compact|formatjson|returnidonly]
# gam <UserTypeEntity> update task <TasklistIDTaskIDEntity>
@@ -69063,9 +69106,9 @@ def getTaskMoveAttribute(myarg, kwargs):
def processTasks(users):
action = Act.Get()
if action != Act.CREATE:
tasklistTaskEntity = getUserObjectEntity(Cmd.OB_TASKLIST_ID_ENTITY, Ent.TASK)
tasklistTaskEntity = getUserObjectEntity(Cmd.OB_TASKLIST_ID_TASK_ID_ENTITY, Ent.TASK, shlexSplit=True)
else:
tasklistTaskEntity = getUserObjectEntity(Cmd.OB_TASKLIST_ID_TASK_ID_ENTITY, Ent.TASK)
tasklistTaskEntity = getUserObjectEntity(Cmd.OB_TASKLIST_ID_ENTITY, Ent.TASK, shlexSplit=True)
if action in {Act.DELETE, Act.CLEAR}:
FJQC = None
checkForExtraneousArguments()
@@ -69093,6 +69136,7 @@ def processTasks(users):
api=API.TASKS, showAction=FJQC is None or not FJQC.formatJSON)
if jcount == 0:
continue
userTasklists = None
Ind.Increment()
j = 0
for tasklistTask in tasklistTasks:
@@ -69104,6 +69148,12 @@ def processTasks(users):
else:
tasklist = tasklistTask
task = body.get('title', '')
if tasklist.startswith('tltitle:'):
tasklistTitle = tasklist[8:]
userTasklists, tasklist = getTaskListIDfromTitle(svc, userTasklists, tasklistTitle, user, i, count)
if tasklist is None:
entityActionFailedWarning([Ent.USER, user, Ent.TASKLIST, tasklistTitle, Ent.TASK, task], Msg.TASKLIST_TITLE_NOT_FOUND, j, jcount)
continue
try:
if action == Act.DELETE:
callGAPI(svc.tasks(), 'delete',
@@ -69163,14 +69213,14 @@ TASK_QUERY_STATE_MAP = {
'showhidden': 'showHidden',
}
# gam <UserTypeEntity> show tasks [tasklists <TasklistIDEntity>]
# gam <UserTypeEntity> show tasks [tasklists <TasklistEntity>]
# [completedmin <Time>] [completedmax <Time>]
# [duemin <Time>] [duemax <Time>]
# [updatedmin <Time>]
# [showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall]
# [orderby completed|due|updated]
# [countsonly|compact|formatjson]
# gam <UserTypeEntity> print tasks [tasklists <TasklistIDEntity>] [todrive <ToDriveAttribute>*]
# gam <UserTypeEntity> print tasks [tasklists <TasklistEntity>] [todrive <ToDriveAttribute>*]
# [completedmin <Time>] [completedmax <Time>]
# [duemin <Time>] [duemax <Time>]
# [updatedmin <Time>]
@@ -69217,7 +69267,6 @@ def printShowTasks(users):
CSVTitle = 'Tasks'
FJQC = FormatJSONQuoteChar(csvPF)
tasklistEntity = None
tlkwargs = {'maxResults': 100}
kwargs = {'maxResults': 100}
compact = countsOnly = False
orderBy = orderByNoDataValue = None
@@ -69226,7 +69275,7 @@ def printShowTasks(users):
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
elif myarg in {'tasklist', 'tasklists'}:
tasklistEntity = getUserObjectEntity(Cmd.OB_TASKLIST_ID_ENTITY, Ent.TASKLIST)
tasklistEntity = getUserObjectEntity(Cmd.OB_TASKLIST_ID_ENTITY, Ent.TASKLIST, shlexSplit=True)
elif myarg in TASK_QUERY_TIME_MAP:
kwargs[TASK_QUERY_TIME_MAP[myarg]] = getTimeOrDeltaFromNow()
elif myarg in TASK_QUERY_STATE_MAP:
@@ -69254,22 +69303,13 @@ def printShowTasks(users):
if not svc:
continue
printGettingEntityItemForWhom(Ent.TASKLIST, user, i, count)
try:
results = callGAPIpages(svc.tasklists(), 'list', 'items',
pageMessage=getPageMessageForWhom(),
throwReasons=GAPI.TASKLIST_THROW_REASONS,
**tlkwargs)
except GAPI.notFound:
results = []
except (GAPI.badRequest, GAPI.invalid) as e:
entityActionFailedWarning([Ent.USER, user, Ent.TASKLIST, None], str(e), i, count)
continue
except GAPI.serviceNotAvailable:
entityServiceNotApplicableWarning(Ent.USER, user, i, count)
results = getTaskLists(svc, user, i, count)
if results is None:
continue
tasklists = [tasklist['id'] for tasklist in results]
jcount = len(tasklists)
else:
userTasklists = None
user, svc, tasklists, jcount = _validateUserGetObjectList(user, i, count, tasklistEntity, api=API.TASKS,
showAction=FJQC is None or not FJQC.formatJSON)
if jcount == 0:
@@ -69281,6 +69321,12 @@ def printShowTasks(users):
j = 0
for tasklist in tasklists:
j += 1
if tasklist.startswith('tltitle:'):
tasklistTitle = tasklist[8:]
userTasklists, tasklist = getTaskListIDfromTitle(svc, userTasklists, tasklistTitle, user, i, count)
if tasklist is None:
entityActionFailedWarning([Ent.USER, user, Ent.TASKLIST, tasklistTitle], Msg.TASKLIST_TITLE_NOT_FOUND, j, jcount)
continue
printGettingEntityItemForWhom(Ent.TASK, tasklist, j, jcount)
try:
tasks = callGAPIpages(svc.tasks(), 'list', 'items',
@@ -69353,17 +69399,17 @@ def _showTasklist(tasklist, j=0, jcount=0, FJQC=None):
# gam <UserTypeEntity> create tasklist
# [title <String>]
# [returnidonly] [formatjson]
# gam <UserTypeEntity> update tasklist <TasklistIDEntity>
# gam <UserTypeEntity> update tasklist <TasklistEntity>
# [title <String>]
# [formatjson]
# gam <UserTypeEntity> info tasklist <TasklistIDEntity>
# gam <UserTypeEntity> info tasklist <TasklistEntity>
# [formatjson]
# gam <UserTypeEntity> delete tasklist <TasklistIDEntity>
# gam <UserTypeEntity> clear tasklist <TasklistIDEntity>
# gam <UserTypeEntity> delete tasklist <TasklistEntity>
# gam <UserTypeEntity> clear tasklist <TasklistEntity>
def processTasklists(users):
action = Act.Get()
if action != Act.CREATE:
tasklistEntity = getUserObjectEntity(Cmd.OB_TASKLIST_ID_ENTITY, Ent.TASKLIST)
tasklistEntity = getUserObjectEntity(Cmd.OB_TASKLIST_ID_ENTITY, Ent.TASKLIST, shlexSplit=True)
else:
tasklistEntity = {'item': Ent.TASKLIST, 'list': [None], 'dict': None}
if action in {Act.DELETE, Act.CLEAR}:
@@ -69384,6 +69430,7 @@ def processTasklists(users):
i, count, users = getEntityArgument(users)
for user in users:
i += 1
userTasklists = None
user, svc, tasklists, jcount = _validateUserGetObjectList(user, i, count, tasklistEntity,
api=API.TASKS,
showAction=action != Act.CREATE and (FJQC is None or not FJQC.formatJSON))
@@ -69393,6 +69440,13 @@ def processTasklists(users):
j = 0
for tasklist in tasklists:
j += 1
if action != Act.CREATE:
if tasklist.startswith('tltitle:'):
tasklistTitle = tasklist[8:]
userTasklists, tasklist = getTaskListIDfromTitle(svc, userTasklists, tasklistTitle, user, i, count)
if tasklist is None:
entityActionFailedWarning([Ent.USER, user, Ent.TASKLIST, tasklistTitle], Msg.TASKLIST_TITLE_NOT_FOUND, j, jcount)
continue
try:
if action == Act.DELETE:
callGAPI(svc.tasklists(), 'delete',
@@ -69445,7 +69499,6 @@ def printShowTasklists(users):
CSVTitle = 'TaskLists'
FJQC = FormatJSONQuoteChar(csvPF)
countsOnly = False
kwargs = {'maxResults': 100}
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if csvPF and myarg == 'todrive':
@@ -69463,18 +69516,8 @@ def printShowTasklists(users):
if not svc:
continue
printGettingAllEntityItemsForWhom(Ent.TASKLIST, user, i, count)
try:
tasklists = callGAPIpages(svc.tasklists(), 'list', 'items',
pageMessage=getPageMessageForWhom(),
throwReasons=GAPI.TASKLIST_THROW_REASONS,
**kwargs)
except GAPI.notFound:
tasklists = []
except (GAPI.badRequest, GAPI.invalid) as e:
entityActionFailedWarning([Ent.USER, user, Ent.TASKLIST, None], str(e), i, count)
continue
except GAPI.serviceNotAvailable:
entityServiceNotApplicableWarning(Ent.USER, user, i, count)
tasklists = getTaskLists(svc, user, i, count)
if tasklists is None:
continue
jcount = len(tasklists)
if countsOnly: