Added option batchsize <Integer> to calendar delete|purge events

This commit is contained in:
Ross Scroggs
2026-01-14 16:24:28 -08:00
parent 01ce6319e8
commit d588f7af43
3 changed files with 85 additions and 40 deletions

View File

@@ -1827,8 +1827,10 @@ gam calendar|calendars <CalendarEntity> import event icaluid <iCalUID> <EventImp
gam calendar|calendars <CalendarEntity> update events [<EventEntity>] [replacemode] <EventUpdateAttribute>+ [<EventNotificationAttribute>] gam calendar|calendars <CalendarEntity> update events [<EventEntity>] [replacemode] <EventUpdateAttribute>+ [<EventNotificationAttribute>]
[showdayofweek] [showdayofweek]
[csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]] [csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
gam calendar|calendars <CalendarEntity> delete events [<EventEntity>] [doit] [<EventNotificationAttribute>] gam calendar|calendars <CalendarEntity> delete events [<EventEntity>]
gam calendar|calendars <CalendarEntity> purge events [<EventEntity>] [doit] [<EventNotificationAttribute>] # [batchsize <Integer>] [doit] [<EventNotificationAttribute>]
gam calendar|calendars <CalendarEntity> purge events [<EventEntity>]
# [batchsize <Integer>] [doit] [<EventNotificationAttribute>]
gam calendar|calendars <CalendarEntity> wipe events gam calendar|calendars <CalendarEntity> wipe events
gam calendar|calendars <CalendarEntity> move events [<EventEntity>] destination|to <CalendarItem> [<EventNotificationAttribute>] gam calendar|calendars <CalendarEntity> move events [<EventEntity>] destination|to <CalendarItem> [<EventNotificationAttribute>]
gam calendar|calendars <CalendarEntity> empty calendartrash gam calendar|calendars <CalendarEntity> empty calendartrash
@@ -6334,8 +6336,10 @@ gam <UserTypeEntity> import event <UserCalendarEntity> icaluid <iCalUID> <EventI
gam <UserTypeEntity> update events <UserCalendarEntity> [<EventEntity>] [replacemode] <EventUpdateAttribute>+ [<EventNotificationAttribute>] gam <UserTypeEntity> update events <UserCalendarEntity> [<EventEntity>] [replacemode] <EventUpdateAttribute>+ [<EventNotificationAttribute>]
[showdayofweek] [showdayofweek]
[csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]] [csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
gam <UserTypeEntity> delete events <UserCalendarEntity> [<EventEntity>] [doit] [<EventNotificationAttribute>] gam <UserTypeEntity> delete events <UserCalendarEntity> [<EventEntity>]
gam <UserTypeEntity> purge events <UserCalendarEntity> [<EventEntity>] [doit] [<EventNotificationAttribute>] # [batchsize <Integer>] [doit] [<EventNotificationAttribute>]
gam <UserTypeEntity> purge events <UserCalendarEntity> [<EventEntity>]
# [batchsize <Integer>] [doit] [<EventNotificationAttribute>]
gam <UserTypeEntity> wipe events <UserCalendarEntity> gam <UserTypeEntity> wipe events <UserCalendarEntity>
gam <UserTypeEntity> move events <UserCalendarEntity> [<EventEntity>] destination|to <CalendarItem> [<EventNotificationAttribute>] gam <UserTypeEntity> move events <UserCalendarEntity> [<EventEntity>] destination|to <CalendarItem> [<EventNotificationAttribute>]
gam <UserTypeEntity> empty calendartrash <UserCalendarEntity> gam <UserTypeEntity> empty calendartrash <UserCalendarEntity>

View File

@@ -1,3 +1,9 @@
7.31.06
Added option `batchsize <Integer>` to `gam calendar <CalendarEntity> delete|purge events` and
`gam <UserTypeEntity> delete|purge events <UserCalendarEntity>` that causes GAM to delete events
with batch API calls rather than with individual API calls.
7.31.05 7.31.05
Added option `variables <RESearchPattern>` to `gam select section <SectionName> verify` and `gam config verify` Added option `variables <RESearchPattern>` to `gam select section <SectionName> verify` and `gam config verify`

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
""" """
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>' __author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.31.05' __version__ = '7.31.06'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)' __license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position #pylint: disable=wrong-import-position
@@ -26640,6 +26640,13 @@ def buildChatServiceObject(api=API.CHAT, user=None, i=0, count=0, entityTypeList
kvList.extend(entityTypeList) kvList.extend(entityTypeList)
return user, chat, kvList return user, chat, kvList
def _getChatPageMessage(entityType, user, i, count, pfilter, useAdminAccess=False):
if user is not None:
printGettingAllEntityItemsForWhom(entityType, user if not useAdminAccess else f'{user}(asadmin)', i, count, pfilter)
return getPageMessageForWhom()
printGettingAllAccountEntities(entityType, pfilter)
return getPageMessage()
def setupChatURL(chat): def setupChatURL(chat):
return f'https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat?project={chat._http.credentials.project_id}' return f'https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat?project={chat._http.credentials.project_id}'
@@ -27109,7 +27116,7 @@ CHAT_UPDATE_SPACE_PERMISSIONS_MAP = {
# [useatmentionall owners|managers|members] # [useatmentionall owners|managers|members]
# [manageapps owners|managers|members] # [manageapps owners|managers|members]
# [managewebhooks owners|managers|members] # [managewebhooks owners|managers|members]
2# [replymessages owners|managers|members] # [replymessages owners|managers|members]
# [formatjson] # [formatjson]
def updateChatSpace(users): def updateChatSpace(users):
FJQC = FormatJSONQuoteChar() FJQC = FormatJSONQuoteChar()
@@ -27278,13 +27285,6 @@ def infoChatSpaceDM(users):
name = convertEmailAddressToUID(getEmailAddress(returnUIDprefix='uid:'), cd, 'user') name = convertEmailAddressToUID(getEmailAddress(returnUIDprefix='uid:'), cd, 'user')
infoChatSpace(users, f'users/{name}') infoChatSpace(users, f'users/{name}')
def _getChatPageMessage(entityType, user, i, count, pfilter, useAdminAccess=False):
if user is not None:
printGettingAllEntityItemsForWhom(entityType, user if not useAdminAccess else f'{user}(asadmin)', i, count, pfilter)
return getPageMessageForWhom()
printGettingAllAccountEntities(entityType, pfilter)
return getPageMessage()
def _getChatSpaceListParms(myarg, kwargs): def _getChatSpaceListParms(myarg, kwargs):
if myarg in {'type', 'types'}: if myarg in {'type', 'types'}:
for ctype in getString(Cmd.OB_GROUP_ROLE_LIST).lower().replace(',', ' ').split(): for ctype in getString(Cmd.OB_GROUP_ROLE_LIST).lower().replace(',', ' ').split():
@@ -40917,7 +40917,7 @@ def doCalendarsUpdateEventsOld(calIds):
_updateCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity, body, parameters) _updateCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity, body, parameters)
def _getCalendarDeleteEventOptions(calendarEventEntity=None): def _getCalendarDeleteEventOptions(calendarEventEntity=None):
parameters = {'sendUpdates': 'none', 'doIt': False} parameters = {'sendUpdates': 'none', 'doIt': False, 'batch_size': 0}
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if _getCalendarSendUpdates(myarg, parameters): if _getCalendarSendUpdates(myarg, parameters):
@@ -40926,11 +40926,22 @@ def _getCalendarDeleteEventOptions(calendarEventEntity=None):
calendarEventEntity['list'].append(getString(Cmd.OB_EVENT_ID)) calendarEventEntity['list'].append(getString(Cmd.OB_EVENT_ID))
elif myarg == 'doit': elif myarg == 'doit':
parameters['doIt'] = True parameters['doIt'] = True
elif myarg == 'batchsize':
parameters['batch_size'] = getInteger(minVal=0, maxVal=1000)
else: else:
unknownArgumentExit() unknownArgumentExit()
return parameters return parameters
def _deleteCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEntity, parameters): def _deleteCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEntity, parameters):
def _callbackDeleteEvents(request_id, _, exception):
ri = request_id.splitlines()
if exception is None:
entityActionPerformed([Ent.CALENDAR, ri[RI_ENTITY], Ent.EVENT, ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT]))
else:
http_status, reason, message = checkGAPIError(exception)
errMsg = getHTTPError({}, http_status, reason, message)
entityActionFailedWarning([Ent.CALENDAR, ri[RI_ENTITY], Ent.EVENT, ri[RI_ITEM]], errMsg, int(ri[RI_J]), int(ri[RI_JCOUNT]))
i = 0 i = 0
for calId in calIds: for calId in calIds:
i += 1 i += 1
@@ -40938,6 +40949,7 @@ def _deleteCalendarEvents(origUser, user, origCal, calIds, count, calendarEventE
if jcount == 0: if jcount == 0:
continue continue
Ind.Increment() Ind.Increment()
if parameters['batch_size'] == 0:
j = 0 j = 0
for eventId in calEventIds: for eventId in calEventIds:
j += 1 j += 1
@@ -40957,15 +40969,35 @@ def _deleteCalendarEvents(origUser, user, origCal, calIds, count, calendarEventE
except GAPI.notACalendarUser: except GAPI.notACalendarUser:
userCalServiceNotEnabledWarning(calId, i, count) userCalServiceNotEnabledWarning(calId, i, count)
break break
else:
svcargs = dict([('calendarId', calId), ('eventId', None), ('sendUpdates', parameters['sendUpdates'])]+GM.Globals[GM.EXTRA_ARGS_LIST])
method = getattr(cal.events(), 'delete')
dbatch = cal.new_batch_http_request(callback=_callbackDeleteEvents)
bcount = 0
j = 0
for eventId in calEventIds:
j += 1
svcparms = svcargs.copy()
svcparms['eventId'] = eventId
dbatch.add(method(**svcparms), request_id=batchRequestID(calId, i, count, j, jcount, svcparms['eventId']))
bcount += 1
if bcount >= parameters['batch_size']:
executeBatch(dbatch)
dbatch = cal.new_batch_http_request(callback=_callbackDeleteEvents)
bcount = 0
if bcount > 0:
dbatch.execute()
Ind.Decrement() Ind.Decrement()
# gam calendars <CalendarEntity> delete event <EventEntity> [doit] [<EventNotificationAttribute>] # gam calendars <CalendarEntity> delete event <EventEntity>
# [batchsize <Integer>] [doit] [<EventNotificationAttribute>]
def doCalendarsDeleteEvents(calIds): def doCalendarsDeleteEvents(calIds):
calendarEventEntity = getCalendarEventEntity() calendarEventEntity = getCalendarEventEntity()
parameters = _getCalendarDeleteEventOptions() parameters = _getCalendarDeleteEventOptions()
_deleteCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity, parameters) _deleteCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity, parameters)
# gam calendar <CalendarEntity> deleteevent (id|eventid <EventID>)+ [doit] [<EventNotificationAttribute>] # gam calendar <CalendarEntity> deleteevent (id|eventid <EventID>)+
# [batchsize <Integer>] [doit] [<EventNotificationAttribute>]
def doCalendarsDeleteEventsOld(calIds): def doCalendarsDeleteEventsOld(calIds):
calendarEventEntity = initCalendarEventEntity() calendarEventEntity = initCalendarEventEntity()
parameters = _getCalendarDeleteEventOptions(calendarEventEntity) parameters = _getCalendarDeleteEventOptions(calendarEventEntity)
@@ -41004,7 +41036,7 @@ def _moveCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEnt
try: try:
callGAPI(cal.events(), 'move', callGAPI(cal.events(), 'move',
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.REQUIRED_ACCESS_LEVEL, throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.REQUIRED_ACCESS_LEVEL,
GAPI.INVALID, GAPI.BAD_REQUEST, GAPI.INVALID, GAPI.BAD_REQUEST, GAPI.EVENT_TYPE_RESTRICTION,
GAPI.CANNOT_CHANGE_ORGANIZER, GAPI.CANNOT_CHANGE_ORGANIZER_OF_INSTANCE], GAPI.CANNOT_CHANGE_ORGANIZER, GAPI.CANNOT_CHANGE_ORGANIZER_OF_INSTANCE],
calendarId=calId, eventId=eventId, destination=newCalId, sendUpdates=parameters['sendUpdates'], fields='') calendarId=calId, eventId=eventId, destination=newCalId, sendUpdates=parameters['sendUpdates'], fields='')
entityModifierNewValueActionPerformed(kvListEvent, Act.MODIFIER_TO, f'{Ent.Singular(Ent.CALENDAR)}: {newCalId}', j, jcount) entityModifierNewValueActionPerformed(kvListEvent, Act.MODIFIER_TO, f'{Ent.Singular(Ent.CALENDAR)}: {newCalId}', j, jcount)
@@ -41016,7 +41048,7 @@ def _moveCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEnt
except GAPI.requiredAccessLevel: except GAPI.requiredAccessLevel:
# Correct "You need to have reader access to this calendar." to "Writer access required to both calendars." # Correct "You need to have reader access to this calendar." to "Writer access required to both calendars."
entityActionFailedWarning(kvListEventNewCal, Msg.WRITER_ACCESS_REQUIRED_TO_BOTH_CALENDARS, j, jcount) entityActionFailedWarning(kvListEventNewCal, Msg.WRITER_ACCESS_REQUIRED_TO_BOTH_CALENDARS, j, jcount)
except (GAPI.forbidden, GAPI.invalid, GAPI.badRequest, except (GAPI.forbidden, GAPI.invalid, GAPI.badRequest, GAPI.eventTypeRestriction,
GAPI.cannotChangeOrganizer, GAPI.cannotChangeOrganizerOfInstance) as e: GAPI.cannotChangeOrganizer, GAPI.cannotChangeOrganizerOfInstance) as e:
entityActionFailedWarning(kvListEventNewCal, str(e), j, jcount) entityActionFailedWarning(kvListEventNewCal, str(e), j, jcount)
except GAPI.notACalendarUser: except GAPI.notACalendarUser:
@@ -41079,7 +41111,8 @@ def _purgeCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEn
except GAPI.notACalendarUser: except GAPI.notACalendarUser:
userCalServiceNotEnabledWarning(calId, i, count) userCalServiceNotEnabledWarning(calId, i, count)
# gam calendars <CalendarEntity> purge event <EventEntity> [doit] [<EventNotificationAttribute>] # gam calendars <CalendarEntity> purge event <EventEntity>
# [batchsize <Integer>] [doit] [<EventNotificationAttribute>]
def doCalendarsPurgeEvents(calIds): def doCalendarsPurgeEvents(calIds):
calendarEventEntity = getCalendarEventEntity() calendarEventEntity = getCalendarEventEntity()
parameters = _getCalendarDeleteEventOptions() parameters = _getCalendarDeleteEventOptions()
@@ -41139,7 +41172,7 @@ def _emptyCalendarTrash(user, origCal, calIds, count):
entityPerformActionNumItems([Ent.CALENDAR, calId], jcount, Ent.TRASHED_EVENT, i, count) entityPerformActionNumItems([Ent.CALENDAR, calId], jcount, Ent.TRASHED_EVENT, i, count)
Ind.Increment() Ind.Increment()
if jcount > 0: if jcount > 0:
_purgeCalendarEvents(user, user, cal, [calId], 1, calendarEventEntity, {'sendUpdates': 'none', 'doIt': True}, True) _purgeCalendarEvents(user, user, cal, [calId], 1, calendarEventEntity, {'sendUpdates': 'none', 'doIt': True, 'batch_size': 0}, True)
if not user: if not user:
Ind.Decrement() Ind.Decrement()
@@ -53792,7 +53825,8 @@ def updateCalendarEvents(users):
_updateCalendarEvents(origUser, user, cal, calIds, jcount, calendarEventEntity, body, parameters) _updateCalendarEvents(origUser, user, cal, calIds, jcount, calendarEventEntity, body, parameters)
Ind.Decrement() Ind.Decrement()
# gam <UserTypeEntity> delete events <UserCalendarEntity> <EventEntity> [doit] [<EventNotificationAttribute>] # gam <UserTypeEntity> delete events <UserCalendarEntity> <EventEntity>
# [batchsize <Integer>] [doit] [<EventNotificationAttribute>]
def deleteCalendarEvents(users): def deleteCalendarEvents(users):
calendarEntity = getUserCalendarEntity() calendarEntity = getUserCalendarEntity()
calendarEventEntity = getCalendarEventEntity() calendarEventEntity = getCalendarEventEntity()
@@ -53808,7 +53842,8 @@ def deleteCalendarEvents(users):
_deleteCalendarEvents(origUser, user, cal, calIds, jcount, calendarEventEntity, parameters) _deleteCalendarEvents(origUser, user, cal, calIds, jcount, calendarEventEntity, parameters)
Ind.Decrement() Ind.Decrement()
# gam <UserTypeEntity> purge events <UserCalendarEntity> <EventEntity> [doit] [<EventNotificationAttribute>] # gam <UserTypeEntity> purge events <UserCalendarEntity> <EventEntity>
# [batchsize <Integer>] [doit] [<EventNotificationAttribute>]
def purgeCalendarEvents(users): def purgeCalendarEvents(users):
calendarEntity = getUserCalendarEntity() calendarEntity = getUserCalendarEntity()
calendarEventEntity = getCalendarEventEntity() calendarEventEntity = getCalendarEventEntity()