gam7 7.19.3__py3-none-any.whl → 7.20.1__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.
Potentially problematic release.
This version of gam7 might be problematic. Click here for more details.
- gam/__init__.py +512 -24
- gam/gamlib/glcfg.py +4 -0
- gam/gamlib/glclargs.py +5 -0
- gam/gamlib/glentity.py +4 -0
- gam/gamlib/glglobals.py +3 -0
- gam/gamlib/glmsgs.py +1 -1
- gam/googleapiclient/version.py +1 -1
- {gam7-7.19.3.dist-info → gam7-7.20.1.dist-info}/METADATA +1 -1
- {gam7-7.19.3.dist-info → gam7-7.20.1.dist-info}/RECORD +12 -12
- {gam7-7.19.3.dist-info → gam7-7.20.1.dist-info}/WHEEL +0 -0
- {gam7-7.19.3.dist-info → gam7-7.20.1.dist-info}/entry_points.txt +0 -0
- {gam7-7.19.3.dist-info → gam7-7.20.1.dist-info}/licenses/LICENSE +0 -0
gam/__init__.py
CHANGED
|
@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
|
|
|
25
25
|
"""
|
|
26
26
|
|
|
27
27
|
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
|
|
28
|
-
__version__ = '7.
|
|
28
|
+
__version__ = '7.20.01'
|
|
29
29
|
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
|
30
30
|
|
|
31
31
|
#pylint: disable=wrong-import-position
|
|
@@ -4731,6 +4731,7 @@ def clearServiceCache(service):
|
|
|
4731
4731
|
return False
|
|
4732
4732
|
|
|
4733
4733
|
DISCOVERY_URIS = [googleapiclient.discovery.V1_DISCOVERY_URI, googleapiclient.discovery.V2_DISCOVERY_URI]
|
|
4734
|
+
CLASSROOM_DEVELOPER_PREVIEW_DISCOVERY_URI = "https://{api}.googleapis.com/$discovery/rest?labels=DEVELOPER_PREVIEW&version={apiVersion}"
|
|
4734
4735
|
|
|
4735
4736
|
# Used for API.CLOUDRESOURCEMANAGER, API.SERVICEUSAGE, API.IAM
|
|
4736
4737
|
def getAPIService(api, httpObj):
|
|
@@ -4750,8 +4751,13 @@ def getService(api, httpObj):
|
|
|
4750
4751
|
triesLimit = 3
|
|
4751
4752
|
for n in range(1, triesLimit+1):
|
|
4752
4753
|
try:
|
|
4754
|
+
if api != API.CLASSROOM or not GC.Values[GC.DEVELOPER_PREVIEW_API_KEY]:
|
|
4755
|
+
discoveryServiceUrl = DISCOVERY_URIS[v2discovery]
|
|
4756
|
+
else:
|
|
4757
|
+
discoveryServiceUrl = CLASSROOM_DEVELOPER_PREVIEW_DISCOVERY_URI
|
|
4758
|
+
developerKey = GC.Values[GC.DEVELOPER_PREVIEW_API_KEY]
|
|
4753
4759
|
service = googleapiclient.discovery.build(api, version, http=httpObj, cache_discovery=False,
|
|
4754
|
-
discoveryServiceUrl=
|
|
4760
|
+
discoveryServiceUrl=discoveryServiceUrl, developerKey=developerKey, static_discovery=False)
|
|
4755
4761
|
GM.Globals[GM.CURRENT_API_SERVICES].setdefault(api, {})
|
|
4756
4762
|
GM.Globals[GM.CURRENT_API_SERVICES][api][version] = service._rootDesc.copy()
|
|
4757
4763
|
if GM.Globals[GM.CACHE_DISCOVERY_ONLY]:
|
|
@@ -26998,31 +27004,33 @@ CHAT_SPACES_ADMIN_ORDERBY_CHOICE_MAP = {
|
|
|
26998
27004
|
|
|
26999
27005
|
# gam [<UserTypeEntity>] show chatspaces
|
|
27000
27006
|
# [types <ChatSpaceTypeList>]
|
|
27001
|
-
# [fields <ChatSpaceFieldNameList>]
|
|
27007
|
+
# [fields <ChatSpaceFieldNameList>] [showaccesssettings]
|
|
27002
27008
|
# [formatjson]
|
|
27003
27009
|
# gam [<UserTypeEntity>] print chatspaces [todrive <ToDriveAttribute>*]
|
|
27004
27010
|
# [types <ChatSpaceTypeList>]
|
|
27005
|
-
# [fields <ChatSpaceFieldNameList>]
|
|
27011
|
+
# [fields <ChatSpaceFieldNameList>] [showaccesssettings]
|
|
27006
27012
|
# [formatjson [quotechar <Character>]]
|
|
27007
27013
|
# gam <UserItem> show chatspaces asadmin
|
|
27008
27014
|
# [query <String>] [querytime<String> <Time>]
|
|
27009
27015
|
# [orderby <ChatSpaceAdminOrderByFieldName> [ascending|descending]]
|
|
27010
|
-
# [fields <ChatSpaceFieldNameList>]
|
|
27016
|
+
# [fields <ChatSpaceFieldNameList>] [showaccesssettings]
|
|
27011
27017
|
# [formatjson]
|
|
27012
27018
|
# gam <UserItem> print chatspaces asadmin [todrive <ToDriveAttribute>*]
|
|
27013
27019
|
# [query <String>] [querytime<String> <Time>]
|
|
27014
27020
|
# [orderby <ChatSpaceAdminOrderByFieldName> [ascending|descending]]
|
|
27015
|
-
# [fields <ChatSpaceFieldNameList>]
|
|
27021
|
+
# [fields <ChatSpaceFieldNameList>] [showaccesssettings]
|
|
27016
27022
|
# [formatjson [quotechar <Character>]]
|
|
27017
27023
|
def printShowChatSpaces(users):
|
|
27018
27024
|
csvPF = CSVPrintFile(['User', 'name'] if not isinstance(users, list) else ['name']) if Act.csvFormat() else None
|
|
27019
27025
|
FJQC = FormatJSONQuoteChar(csvPF)
|
|
27020
27026
|
OBY = OrderBy(CHAT_SPACES_ADMIN_ORDERBY_CHOICE_MAP)
|
|
27021
27027
|
useAdminAccess, api, kwargsCS = _getChatAdminAccess(API.CHAT_SPACES_ADMIN, API.CHAT_SPACES)
|
|
27028
|
+
kwargsSAS = {'useAdminAccess': useAdminAccess}
|
|
27022
27029
|
fieldsList = []
|
|
27023
27030
|
queries = []
|
|
27024
27031
|
queryTimes = {}
|
|
27025
27032
|
pfilter = ''
|
|
27033
|
+
showAccessSettings = False
|
|
27026
27034
|
if useAdminAccess:
|
|
27027
27035
|
function = 'search'
|
|
27028
27036
|
queries = ['customer = "customers/my_customer" AND spaceType = "SPACE"']
|
|
@@ -27038,8 +27046,12 @@ def printShowChatSpaces(users):
|
|
|
27038
27046
|
pass
|
|
27039
27047
|
elif useAdminAccess and _getChatSpaceSearchParms(myarg, queries, queryTimes, OBY):
|
|
27040
27048
|
pass
|
|
27049
|
+
elif myarg == 'showaccesssettings':
|
|
27050
|
+
showAccessSettings = True
|
|
27041
27051
|
else:
|
|
27042
27052
|
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
|
27053
|
+
if showAccessSettings and fieldsList:
|
|
27054
|
+
fieldsList.extend(['name', 'spaceType'])
|
|
27043
27055
|
fields = getItemFieldsFromFieldsList('spaces', fieldsList)
|
|
27044
27056
|
i, count, users = getEntityArgument(users)
|
|
27045
27057
|
if useAdminAccess:
|
|
@@ -27064,6 +27076,17 @@ def printShowChatSpaces(users):
|
|
|
27064
27076
|
GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
|
|
27065
27077
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
27066
27078
|
fields=fields, pageSize=CHAT_PAGE_SIZE, **kwargsCS)
|
|
27079
|
+
if showAccessSettings:
|
|
27080
|
+
for space in spaces:
|
|
27081
|
+
if space['spaceType'] == 'SPACE':
|
|
27082
|
+
try:
|
|
27083
|
+
result = callGAPI(chat.spaces(), 'get',
|
|
27084
|
+
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
|
|
27085
|
+
GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
|
|
27086
|
+
name=space['name'], fields='accessSettings', **kwargsSAS)
|
|
27087
|
+
space.update(result)
|
|
27088
|
+
except (GAPI.notFound, GAPI.invalidArgument, GAPI.internalError, GAPI.permissionDenied, GAPI.failedPrecondition):
|
|
27089
|
+
pass
|
|
27067
27090
|
except (GAPI.notFound, GAPI.invalidArgument, GAPI.internalError, GAPI.permissionDenied) as e:
|
|
27068
27091
|
exitIfChatNotConfigured(chat, kvList, str(e), i, count)
|
|
27069
27092
|
continue
|
|
@@ -48430,6 +48453,14 @@ def _convertCourseUserIdToEmail(croom, userId, emails, entityValueList, i, count
|
|
|
48430
48453
|
emails[userId] = userEmail
|
|
48431
48454
|
return userEmail
|
|
48432
48455
|
|
|
48456
|
+
def _getCourseOwnerSA(croom, course, useOwnerAccess):
|
|
48457
|
+
if not useOwnerAccess:
|
|
48458
|
+
return croom
|
|
48459
|
+
courseOwnerId = course["ownerId"]
|
|
48460
|
+
if courseOwnerId not in GM.Globals[GM.CLASSROOM_OWNER_SA]:
|
|
48461
|
+
_, GM.Globals[GM.CLASSROOM_OWNER_SA][courseOwnerId] = buildGAPIServiceObject(API.CLASSROOM, f'uid:{courseOwnerId}')
|
|
48462
|
+
return GM.Globals[GM.CLASSROOM_OWNER_SA][courseOwnerId]
|
|
48463
|
+
|
|
48433
48464
|
def _getCoursesOwnerInfo(croom, courseIds, useOwnerAccess, addCIIdScope=True):
|
|
48434
48465
|
coursesInfo = {}
|
|
48435
48466
|
for courseId in courseIds:
|
|
@@ -48443,13 +48474,10 @@ def _getCoursesOwnerInfo(croom, courseIds, useOwnerAccess, addCIIdScope=True):
|
|
|
48443
48474
|
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE,
|
|
48444
48475
|
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
|
|
48445
48476
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
48446
|
-
id=courseId, fields='name,ownerId')
|
|
48447
|
-
|
|
48448
|
-
_, ocroom = buildGAPIServiceObject(API.CLASSROOM, f'uid:{course["ownerId"]}')
|
|
48449
|
-
else:
|
|
48450
|
-
ocroom = croom
|
|
48477
|
+
id=courseId, fields='id,name,ownerId')
|
|
48478
|
+
ocroom = _getCourseOwnerSA(croom, course, useOwnerAccess)
|
|
48451
48479
|
if ocroom is not None:
|
|
48452
|
-
coursesInfo[ciCourseId] = {'name': course['name'], 'croom': ocroom}
|
|
48480
|
+
coursesInfo[ciCourseId] = {'id': course['id'], 'name': course['name'], 'croom': ocroom}
|
|
48453
48481
|
except GAPI.notFound:
|
|
48454
48482
|
entityDoesNotExistWarning(Ent.COURSE, courseId)
|
|
48455
48483
|
except GAPI.serviceNotAvailable as e:
|
|
@@ -48836,12 +48864,9 @@ def doPrintCourses():
|
|
|
48836
48864
|
for field in courseShowProperties['skips']:
|
|
48837
48865
|
course.pop(field, None)
|
|
48838
48866
|
courseId = course['id']
|
|
48839
|
-
|
|
48840
|
-
|
|
48841
|
-
|
|
48842
|
-
continue
|
|
48843
|
-
else:
|
|
48844
|
-
ocroom = croom
|
|
48867
|
+
ocroom = _getCourseOwnerSA(croom, course, useOwnerAccess)
|
|
48868
|
+
if not ocroom:
|
|
48869
|
+
continue
|
|
48845
48870
|
if courseShowProperties['ownerEmail']:
|
|
48846
48871
|
course['ownerEmail'] = _convertCourseUserIdToEmail(croom, course['ownerId'], ownerEmails,
|
|
48847
48872
|
[Ent.COURSE, courseId, Ent.OWNER_ID, course['ownerId']], i, count)
|
|
@@ -49651,12 +49676,9 @@ def doPrintCourseParticipants():
|
|
|
49651
49676
|
for course in coursesInfo:
|
|
49652
49677
|
i += 1
|
|
49653
49678
|
courseId = course['id']
|
|
49654
|
-
|
|
49655
|
-
|
|
49656
|
-
|
|
49657
|
-
continue
|
|
49658
|
-
else:
|
|
49659
|
-
ocroom = croom
|
|
49679
|
+
ocroom = _getCourseOwnerSA(croom, course, useOwnerAccess)
|
|
49680
|
+
if not ocroom:
|
|
49681
|
+
continue
|
|
49660
49682
|
_, teachers, students = _getCourseAliasesMembers(croom, ocroom, courseId, courseShowProperties, teachersFields, studentsFields, True, i, count)
|
|
49661
49683
|
if showItemCountOnly:
|
|
49662
49684
|
if courseShowProperties['members'] != 'students':
|
|
@@ -51209,6 +51231,461 @@ def printShowClassroomProfile(users):
|
|
|
51209
51231
|
if csvPF:
|
|
51210
51232
|
csvPF.writeCSVfile('Classroom User Profiles')
|
|
51211
51233
|
|
|
51234
|
+
# gam create course-studentgroups
|
|
51235
|
+
# (course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] [states <CourseStateList>])
|
|
51236
|
+
# title <String>
|
|
51237
|
+
# [csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
|
|
51238
|
+
def doCreateCourseStudentGroups():
|
|
51239
|
+
croom = buildGAPIObject(API.CLASSROOM)
|
|
51240
|
+
csvPF = None
|
|
51241
|
+
FJQC = FormatJSONQuoteChar(None)
|
|
51242
|
+
courseSelectionParameters = _initCourseSelectionParameters()
|
|
51243
|
+
courseShowProperties = _initCourseShowProperties(['name'])
|
|
51244
|
+
useOwnerAccess = GC.Values[GC.USE_COURSE_OWNER_ACCESS]
|
|
51245
|
+
kwargs = {'courseId': None, 'body': {}}
|
|
51246
|
+
while Cmd.ArgumentsRemaining():
|
|
51247
|
+
myarg = getArgument()
|
|
51248
|
+
if myarg == 'title':
|
|
51249
|
+
kwargs['body']['title'] = getString(Cmd.OB_STRING)
|
|
51250
|
+
elif _getCourseSelectionParameters(myarg, courseSelectionParameters):
|
|
51251
|
+
pass
|
|
51252
|
+
elif myarg == 'csv':
|
|
51253
|
+
csvPF = CSVPrintFile(['courseId', 'courseName', 'studentGroupId', 'studentGroupTitle'])
|
|
51254
|
+
FJQC = FormatJSONQuoteChar(csvPF)
|
|
51255
|
+
elif csvPF and myarg == 'todrive':
|
|
51256
|
+
csvPF.GetTodriveParameters()
|
|
51257
|
+
else:
|
|
51258
|
+
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
|
51259
|
+
if 'title' not in kwargs['body']:
|
|
51260
|
+
missingArgumentExit('title')
|
|
51261
|
+
if csvPF and FJQC.formatJSON:
|
|
51262
|
+
csvPF.SetJSONTitles(['courseId', 'courseName', 'JSON'])
|
|
51263
|
+
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties, useOwnerAccess)
|
|
51264
|
+
if coursesInfo is None:
|
|
51265
|
+
return
|
|
51266
|
+
count = len(coursesInfo)
|
|
51267
|
+
i = 0
|
|
51268
|
+
for course in coursesInfo:
|
|
51269
|
+
i += 1
|
|
51270
|
+
courseId = course['id']
|
|
51271
|
+
ocroom = _getCourseOwnerSA(croom, course, useOwnerAccess)
|
|
51272
|
+
if not ocroom:
|
|
51273
|
+
continue
|
|
51274
|
+
kwargs['courseId'] = courseId
|
|
51275
|
+
kvList = [Ent.COURSE, courseId, Ent.COURSE_STUDENTGROUP, None]
|
|
51276
|
+
try:
|
|
51277
|
+
studentGroup = callGAPI(ocroom.courses().studentGroups(), 'create',
|
|
51278
|
+
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_IMPLEMENTED,
|
|
51279
|
+
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
|
|
51280
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
51281
|
+
previewVersion='V1_20250630_PREVIEW',
|
|
51282
|
+
**kwargs)
|
|
51283
|
+
kvList[-1] = f"{studentGroup['title']}({studentGroup['id']})"
|
|
51284
|
+
if not csvPF:
|
|
51285
|
+
entityActionPerformed(kvList, i, count)
|
|
51286
|
+
elif not FJQC.formatJSON:
|
|
51287
|
+
csvPF.WriteRow({'courseId': courseId, 'courseName': course['name'],
|
|
51288
|
+
'studentGroupId': studentGroup['id'], 'studentGroupTitle': studentGroup['title']})
|
|
51289
|
+
else:
|
|
51290
|
+
csvPF.WriteRowNoFilter({'courseId': courseId, 'courseName': course['name'],
|
|
51291
|
+
'JSON': json.dumps(cleanJSON(studentGroup), ensure_ascii=False, sort_keys=True)})
|
|
51292
|
+
except GAPI.notFound as e:
|
|
51293
|
+
entityActionFailedWarning(kvList, str(e), i, count)
|
|
51294
|
+
except (GAPI.serviceNotAvailable, GAPI.notImplemented) as e:
|
|
51295
|
+
entityActionFailedExit([Ent.COURSE, courseId], str(e), i, count)
|
|
51296
|
+
except (GAPI.forbidden, GAPI.permissionDenied) as e:
|
|
51297
|
+
ClientAPIAccessDeniedExit(str(e))
|
|
51298
|
+
if csvPF:
|
|
51299
|
+
csvPF.writeCSVfile('Course Student Groups')
|
|
51300
|
+
|
|
51301
|
+
# gam update course-studentgroup <CourseID> <StudentGroupID> title <String>
|
|
51302
|
+
def doUpdateCourseStudentGroups():
|
|
51303
|
+
croom = buildGAPIObject(API.CLASSROOM)
|
|
51304
|
+
courseId = getString(Cmd.OB_COURSE_ID)
|
|
51305
|
+
studentGroupId = getString(Cmd.OB_STUDENTGROUP_ID)
|
|
51306
|
+
kwargs = {'courseId': courseId, 'id': studentGroupId, 'body': {}, 'updateMask': ''}
|
|
51307
|
+
while Cmd.ArgumentsRemaining():
|
|
51308
|
+
myarg = getArgument()
|
|
51309
|
+
if myarg == 'title':
|
|
51310
|
+
kwargs['body']['title'] = getString(Cmd.OB_STRING)
|
|
51311
|
+
kwargs['updateMask'] = myarg
|
|
51312
|
+
else:
|
|
51313
|
+
unknownArgumentExit()
|
|
51314
|
+
if 'title' not in kwargs['body']:
|
|
51315
|
+
missingArgumentExit('title')
|
|
51316
|
+
_, count, coursesInfo = _getCoursesOwnerInfo(croom, [courseId], GC.Values[GC.USE_COURSE_OWNER_ACCESS])
|
|
51317
|
+
if count == 0:
|
|
51318
|
+
return
|
|
51319
|
+
ocroom = coursesInfo[courseId]['croom']
|
|
51320
|
+
courseId = coursesInfo[courseId]['id']
|
|
51321
|
+
kvList = [Ent.COURSE, courseId, Ent.COURSE_STUDENTGROUP, studentGroupId]
|
|
51322
|
+
try:
|
|
51323
|
+
studentGroup = callGAPI(ocroom.courses().studentGroups(), 'patch',
|
|
51324
|
+
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_IMPLEMENTED,
|
|
51325
|
+
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
|
|
51326
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
51327
|
+
previewVersion='V1_20250630_PREVIEW',
|
|
51328
|
+
**kwargs)
|
|
51329
|
+
kvList[-1] = f"{studentGroup['title']}({studentGroup['id']})"
|
|
51330
|
+
entityActionPerformed(kvList)
|
|
51331
|
+
except GAPI.notFound as e:
|
|
51332
|
+
entityActionFailedWarning(kvList, str(e))
|
|
51333
|
+
except (GAPI.serviceNotAvailable, GAPI.notImplemented) as e:
|
|
51334
|
+
entityActionFailedExit([Ent.COURSE, courseId], str(e))
|
|
51335
|
+
except (GAPI.forbidden, GAPI.permissionDenied) as e:
|
|
51336
|
+
ClientAPIAccessDeniedExit(str(e))
|
|
51337
|
+
|
|
51338
|
+
# gam delete course-studentgroups <CourseID> <StudentGroupIDEntity>
|
|
51339
|
+
def doDeleteCourseStudentGroups():
|
|
51340
|
+
croom = buildGAPIObject(API.CLASSROOM)
|
|
51341
|
+
courseId = getString(Cmd.OB_COURSE_ID)
|
|
51342
|
+
studentGroupIds = getEntityList(Cmd.OB_STUDENTGROUP_ID_ENTITY, shlexSplit=False)
|
|
51343
|
+
checkForExtraneousArguments()
|
|
51344
|
+
_, count, coursesInfo = _getCoursesOwnerInfo(croom, [courseId], GC.Values[GC.USE_COURSE_OWNER_ACCESS])
|
|
51345
|
+
if count == 0:
|
|
51346
|
+
return
|
|
51347
|
+
ocroom = coursesInfo[courseId]['croom']
|
|
51348
|
+
courseId = coursesInfo[courseId]['id']
|
|
51349
|
+
kwargs = {'courseId': courseId, 'id': None}
|
|
51350
|
+
kvList = [Ent.COURSE, courseId, Ent.COURSE_STUDENTGROUP, None]
|
|
51351
|
+
count = len(studentGroupIds)
|
|
51352
|
+
i = 0
|
|
51353
|
+
for studentGroupId in studentGroupIds:
|
|
51354
|
+
i += 1
|
|
51355
|
+
kwargs['id'] = kvList[-1] = studentGroupId
|
|
51356
|
+
try:
|
|
51357
|
+
callGAPI(ocroom.courses().studentGroups(), 'delete',
|
|
51358
|
+
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_IMPLEMENTED,
|
|
51359
|
+
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
|
|
51360
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
51361
|
+
previewVersion='V1_20250630_PREVIEW',
|
|
51362
|
+
**kwargs)
|
|
51363
|
+
entityActionPerformed(kvList, i, count)
|
|
51364
|
+
except GAPI.notFound as e:
|
|
51365
|
+
entityActionFailedWarning(kvList, str(e), i, count)
|
|
51366
|
+
except (GAPI.serviceNotAvailable, GAPI.notImplemented) as e:
|
|
51367
|
+
entityActionFailedExit([Ent.COURSE, courseId], str(e), i, count)
|
|
51368
|
+
except (GAPI.forbidden, GAPI.permissionDenied) as e:
|
|
51369
|
+
ClientAPIAccessDeniedExit(str(e))
|
|
51370
|
+
|
|
51371
|
+
# gam clear course-studentgroups
|
|
51372
|
+
# (course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] [states <CourseStateList>])
|
|
51373
|
+
def doClearCourseStudentGroups():
|
|
51374
|
+
croom = buildGAPIObject(API.CLASSROOM)
|
|
51375
|
+
courseSelectionParameters = _initCourseSelectionParameters()
|
|
51376
|
+
courseShowProperties = _initCourseShowProperties(['name'])
|
|
51377
|
+
useOwnerAccess = GC.Values[GC.USE_COURSE_OWNER_ACCESS]
|
|
51378
|
+
while Cmd.ArgumentsRemaining():
|
|
51379
|
+
myarg = getArgument()
|
|
51380
|
+
if _getCourseSelectionParameters(myarg, courseSelectionParameters):
|
|
51381
|
+
pass
|
|
51382
|
+
else:
|
|
51383
|
+
unknownArgumentExit()
|
|
51384
|
+
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties, useOwnerAccess)
|
|
51385
|
+
if coursesInfo is None:
|
|
51386
|
+
return
|
|
51387
|
+
count = len(coursesInfo)
|
|
51388
|
+
i = 0
|
|
51389
|
+
for course in coursesInfo:
|
|
51390
|
+
i += 1
|
|
51391
|
+
courseId = course['id']
|
|
51392
|
+
ocroom = _getCourseOwnerSA(croom, course, useOwnerAccess)
|
|
51393
|
+
if not ocroom:
|
|
51394
|
+
continue
|
|
51395
|
+
kwargs = {'courseId': courseId, 'id': None}
|
|
51396
|
+
kvList = [Ent.COURSE, courseId, Ent.COURSE_STUDENTGROUP, None]
|
|
51397
|
+
studentGroups = []
|
|
51398
|
+
printGettingEntityItemForWhom(Ent.COURSE_STUDENTGROUP, formatKeyValueList('', [Ent.Singular(Ent.COURSE), courseId], currentCount(i, count)))
|
|
51399
|
+
pageMessage = getPageMessage()
|
|
51400
|
+
try:
|
|
51401
|
+
studentGroups = callGAPIpages(ocroom.courses().studentGroups(), 'list', 'studentGroups',
|
|
51402
|
+
pageMessage=pageMessage,
|
|
51403
|
+
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_IMPLEMENTED,
|
|
51404
|
+
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
|
|
51405
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
51406
|
+
previewVersion='V1_20250630_PREVIEW',
|
|
51407
|
+
courseId=courseId)
|
|
51408
|
+
except GAPI.notFound as e:
|
|
51409
|
+
entityActionFailedWarning([Ent.COURSE, courseId], str(e))
|
|
51410
|
+
continue
|
|
51411
|
+
except (GAPI.serviceNotAvailable, GAPI.notImplemented) as e:
|
|
51412
|
+
entityActionFailedExit([Ent.COURSE, courseId], str(e))
|
|
51413
|
+
except (GAPI.forbidden, GAPI.permissionDenied) as e:
|
|
51414
|
+
ClientAPIAccessDeniedExit(str(e))
|
|
51415
|
+
jcount = len(studentGroups)
|
|
51416
|
+
entityPerformActionNumItems([Ent.COURSE, courseId], jcount, Ent.COURSE_STUDENTGROUP, i, count)
|
|
51417
|
+
Ind.Increment()
|
|
51418
|
+
j = 0
|
|
51419
|
+
for studentGroup in studentGroups:
|
|
51420
|
+
j += 1
|
|
51421
|
+
kwargs['id'] = kvList[-1] = studentGroup['id']
|
|
51422
|
+
try:
|
|
51423
|
+
callGAPI(ocroom.courses().studentGroups(), 'delete',
|
|
51424
|
+
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_IMPLEMENTED,
|
|
51425
|
+
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
|
|
51426
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
51427
|
+
previewVersion='V1_20250630_PREVIEW',
|
|
51428
|
+
**kwargs)
|
|
51429
|
+
entityActionPerformed(kvList, j, jcount)
|
|
51430
|
+
except GAPI.notFound as e:
|
|
51431
|
+
entityActionFailedWarning(kvList, str(e), j, jcount)
|
|
51432
|
+
except (GAPI.serviceNotAvailable, GAPI.notImplemented) as e:
|
|
51433
|
+
entityActionFailedExit([Ent.COURSE, courseId], str(e), j, jcount)
|
|
51434
|
+
except (GAPI.forbidden, GAPI.permissionDenied) as e:
|
|
51435
|
+
ClientAPIAccessDeniedExit(str(e))
|
|
51436
|
+
Ind.Decrement()
|
|
51437
|
+
|
|
51438
|
+
# gam print course-studentgroups [todrive <ToDriveAttribute>*]
|
|
51439
|
+
# (course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] [states <CourseStateList>])
|
|
51440
|
+
# [showitemcountonly] [formatjson [quotechar <Character>]]
|
|
51441
|
+
def doPrintCourseStudentGroups(showMembers=False):
|
|
51442
|
+
croom = buildGAPIObject(API.CLASSROOM)
|
|
51443
|
+
cd = buildGAPIObject(API.DIRECTORY)
|
|
51444
|
+
csvPF = CSVPrintFile(['courseId', 'courseName', 'studentGroupId', 'studentGroupTitle'])
|
|
51445
|
+
FJQC = FormatJSONQuoteChar(csvPF)
|
|
51446
|
+
courseSelectionParameters = _initCourseSelectionParameters()
|
|
51447
|
+
courseShowProperties = _initCourseShowProperties(['name'])
|
|
51448
|
+
showItemCountOnly = False
|
|
51449
|
+
useOwnerAccess = GC.Values[GC.USE_COURSE_OWNER_ACCESS]
|
|
51450
|
+
while Cmd.ArgumentsRemaining():
|
|
51451
|
+
myarg = getArgument()
|
|
51452
|
+
if myarg == 'todrive':
|
|
51453
|
+
csvPF.GetTodriveParameters()
|
|
51454
|
+
elif _getCourseSelectionParameters(myarg, courseSelectionParameters):
|
|
51455
|
+
pass
|
|
51456
|
+
elif myarg == 'showitemcountonly':
|
|
51457
|
+
showItemCountOnly = True
|
|
51458
|
+
else:
|
|
51459
|
+
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
|
51460
|
+
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties, useOwnerAccess)
|
|
51461
|
+
if coursesInfo is None:
|
|
51462
|
+
if showItemCountOnly:
|
|
51463
|
+
writeStdout('0\n')
|
|
51464
|
+
return
|
|
51465
|
+
itemCount = 0
|
|
51466
|
+
count = len(coursesInfo)
|
|
51467
|
+
i = 0
|
|
51468
|
+
for course in coursesInfo:
|
|
51469
|
+
i += 1
|
|
51470
|
+
courseId = course['id']
|
|
51471
|
+
ocroom = _getCourseOwnerSA(croom, course, useOwnerAccess)
|
|
51472
|
+
if not ocroom:
|
|
51473
|
+
continue
|
|
51474
|
+
studentGroups = []
|
|
51475
|
+
printGettingEntityItemForWhom(Ent.COURSE_STUDENTGROUP, formatKeyValueList('', [Ent.Singular(Ent.COURSE), courseId], currentCount(i, count)))
|
|
51476
|
+
pageMessage = getPageMessage()
|
|
51477
|
+
try:
|
|
51478
|
+
studentGroups = callGAPIpages(ocroom.courses().studentGroups(), 'list', 'studentGroups',
|
|
51479
|
+
pageMessage=pageMessage,
|
|
51480
|
+
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_IMPLEMENTED,
|
|
51481
|
+
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
|
|
51482
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
51483
|
+
previewVersion='V1_20250630_PREVIEW',
|
|
51484
|
+
courseId=courseId)
|
|
51485
|
+
except GAPI.notFound as e:
|
|
51486
|
+
entityActionFailedWarning([Ent.COURSE, courseId], str(e))
|
|
51487
|
+
continue
|
|
51488
|
+
except (GAPI.serviceNotAvailable, GAPI.notImplemented) as e:
|
|
51489
|
+
entityActionFailedExit([Ent.COURSE, courseId], str(e))
|
|
51490
|
+
except (GAPI.forbidden, GAPI.permissionDenied) as e:
|
|
51491
|
+
ClientAPIAccessDeniedExit(str(e))
|
|
51492
|
+
if not showMembers and showItemCountOnly:
|
|
51493
|
+
itemCount += len(studentGroups)
|
|
51494
|
+
continue
|
|
51495
|
+
for studentGroup in studentGroups:
|
|
51496
|
+
studentGroupId = studentGroup['id']
|
|
51497
|
+
if not showMembers:
|
|
51498
|
+
if not FJQC.formatJSON:
|
|
51499
|
+
csvPF.WriteRowTitles({'courseId': courseId, 'courseName': course['name'],
|
|
51500
|
+
'studentGroupId': studentGroupId, 'studentGroupTitle': studentGroup['title']})
|
|
51501
|
+
else:
|
|
51502
|
+
row = {'courseId': courseId, 'courseName': course['name']}
|
|
51503
|
+
if csvPF.CheckRowTitles(row):
|
|
51504
|
+
row['JSON'] = json.dumps(cleanJSON(studentGroup), ensure_ascii=False, sort_keys=False)
|
|
51505
|
+
csvPF.WriteRowTitles(row)
|
|
51506
|
+
continue
|
|
51507
|
+
printGettingEntityItemForWhom(Ent.USER, formatKeyValueList('', [Ent.Singular(Ent.COURSE_STUDENTGROUP), studentGroupId],
|
|
51508
|
+
currentCount(i, count)))
|
|
51509
|
+
pageMessage = getPageMessage()
|
|
51510
|
+
try:
|
|
51511
|
+
students = callGAPIpages(ocroom.courses().studentGroups().studentGroupMembers(), 'list', 'studentGroupMembers',
|
|
51512
|
+
pageMessage=pageMessage,
|
|
51513
|
+
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE,
|
|
51514
|
+
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
|
|
51515
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
51516
|
+
previewVersion='V1_20250630_PREVIEW',
|
|
51517
|
+
courseId=courseId, studentGroupId=studentGroupId)
|
|
51518
|
+
if showItemCountOnly:
|
|
51519
|
+
itemCount += len(students)
|
|
51520
|
+
continue
|
|
51521
|
+
for member in students:
|
|
51522
|
+
member['userEmail'] = convertUIDtoEmailAddress(f"id:{member['userId']}", cd=cd, emailTypes=['user'])
|
|
51523
|
+
except GAPI.notFound as e:
|
|
51524
|
+
entityActionFailedWarning([Ent.COURSE, courseId, Ent.COURSE_STUDENTGROUP, studentGroupId], str(e))
|
|
51525
|
+
continue
|
|
51526
|
+
except (GAPI.serviceNotAvailable, GAPI.notImplemented) as e:
|
|
51527
|
+
entityActionFailedExit([Ent.COURSE, courseId, Ent.COURSE_STUDENTGROUP, studentGroupId], str(e))
|
|
51528
|
+
except (GAPI.forbidden, GAPI.permissionDenied) as e:
|
|
51529
|
+
ClientAPIAccessDeniedExit(str(e))
|
|
51530
|
+
if not FJQC.formatJSON:
|
|
51531
|
+
row = {'courseId': courseId, 'courseName': course['name'],
|
|
51532
|
+
'studentGroupId': studentGroupId, 'studentGroupTitle': studentGroup['title']}
|
|
51533
|
+
for member in students:
|
|
51534
|
+
csvPF.WriteRowTitles(flattenJSON(member, flattened=row.copy()))
|
|
51535
|
+
else:
|
|
51536
|
+
row = {'courseId': courseId, 'courseName': course['name'],
|
|
51537
|
+
'studentGroupId': studentGroupId, 'studentGroupTitle': studentGroup['title']}
|
|
51538
|
+
row['JSON'] = json.dumps(list(students))
|
|
51539
|
+
csvPF.WriteRowNoFilter(row)
|
|
51540
|
+
if showItemCountOnly:
|
|
51541
|
+
writeStdout(f'{itemCount}\n')
|
|
51542
|
+
return
|
|
51543
|
+
if not showMembers:
|
|
51544
|
+
title = 'Course Student Groups'
|
|
51545
|
+
else:
|
|
51546
|
+
title = 'Course Student Group Members'
|
|
51547
|
+
csvPF.writeCSVfile(title)
|
|
51548
|
+
|
|
51549
|
+
# gam create course-studentgroup-members <CourseID> <StudentGroupID> <UserTypeEntity>
|
|
51550
|
+
# gam delete course-studentgroup-members <CourseID> <StudentGroupID> <UserTypeEntity>
|
|
51551
|
+
# gam sync course-studentgroup-members <CourseID> <StudentGroupID> <UserTypeEntity>
|
|
51552
|
+
# gam clear course-studentgroup-members <CourseID> <StudentGroupID>
|
|
51553
|
+
def doProcessCourseStudentGroupMembers():
|
|
51554
|
+
def _getCurrentStudents():
|
|
51555
|
+
printGettingEntityItemForWhom(Ent.USER, Ent.Singular(Ent.COURSE_STUDENTGROUP), studentGroupId)
|
|
51556
|
+
pageMessage = getPageMessage()
|
|
51557
|
+
try:
|
|
51558
|
+
return callGAPIpages(ocroom.courses().studentGroups().studentGroupMembers(), 'list', 'studentGroupMembers',
|
|
51559
|
+
pageMessage=pageMessage,
|
|
51560
|
+
throwReasons=[GAPI.NOT_FOUND, GAPI.SERVICE_NOT_AVAILABLE,
|
|
51561
|
+
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
|
|
51562
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
51563
|
+
previewVersion='V1_20250630_PREVIEW',
|
|
51564
|
+
courseId=courseId, studentGroupId=studentGroupId)
|
|
51565
|
+
except GAPI.notFound as e:
|
|
51566
|
+
entityActionFailedWarning([Ent.COURSE, courseId, Ent.COURSE_STUDENTGROUP, studentGroupId], str(e))
|
|
51567
|
+
return []
|
|
51568
|
+
except (GAPI.serviceNotAvailable, GAPI.notImplemented) as e:
|
|
51569
|
+
entityActionFailedExit([Ent.COURSE, courseId, Ent.COURSE_STUDENTGROUP, studentGroupId], str(e))
|
|
51570
|
+
except (GAPI.forbidden, GAPI.permissionDenied) as e:
|
|
51571
|
+
ClientAPIAccessDeniedExit(str(e))
|
|
51572
|
+
|
|
51573
|
+
def _getStudentUserId(kvList, student, i, count):
|
|
51574
|
+
normalizedEmailAddressOrUID = normalizeEmailAddressOrUID(student)
|
|
51575
|
+
if normalizedEmailAddressOrUID.find('@') == -1:
|
|
51576
|
+
return normalizedEmailAddressOrUID
|
|
51577
|
+
try:
|
|
51578
|
+
return callGAPI(cd.users(), 'get',
|
|
51579
|
+
throwReasons=GAPI.USER_GET_THROW_REASONS,
|
|
51580
|
+
userKey=normalizedEmailAddressOrUID, fields='id')['id']
|
|
51581
|
+
except (GAPI.userNotFound, GAPI.domainNotFound, GAPI.domainCannotUseApis, GAPI.forbidden,
|
|
51582
|
+
GAPI.badRequest, GAPI.backendError, GAPI.systemError) as e:
|
|
51583
|
+
entityActionFailedWarning(kvList, str(e), i, count)
|
|
51584
|
+
return None
|
|
51585
|
+
|
|
51586
|
+
def _processStudent(function, kvList, kwargs, i, count):
|
|
51587
|
+
try:
|
|
51588
|
+
callGAPI(ocroom.courses().studentGroups().studentGroupMembers(), function,
|
|
51589
|
+
throwReasons=[GAPI.NOT_FOUND, GAPI.ALREADY_EXISTS,
|
|
51590
|
+
GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_IMPLEMENTED,
|
|
51591
|
+
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
|
|
51592
|
+
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
51593
|
+
previewVersion='V1_20250630_PREVIEW',
|
|
51594
|
+
**kwargs)
|
|
51595
|
+
entityActionPerformed(kvList, i, count)
|
|
51596
|
+
except (GAPI.alreadyExists, GAPI.notFound) as e:
|
|
51597
|
+
entityActionFailedWarning(kvList, str(e), i, count)
|
|
51598
|
+
except (GAPI.serviceNotAvailable, GAPI.notImplemented) as e:
|
|
51599
|
+
entityActionFailedExit([Ent.COURSE, courseId], str(e))
|
|
51600
|
+
except (GAPI.forbidden, GAPI.permissionDenied) as e:
|
|
51601
|
+
ClientAPIAccessDeniedExit(str(e))
|
|
51602
|
+
|
|
51603
|
+
def _addStudents(students, getUserIds):
|
|
51604
|
+
count = len(students)
|
|
51605
|
+
i = 0
|
|
51606
|
+
entityPerformActionNumItems([Ent.COURSE, courseId, Ent.COURSE_STUDENTGROUP, studentGroupId], count, Ent.USER)
|
|
51607
|
+
kvList = [Ent.COURSE, courseId, Ent.COURSE_STUDENTGROUP, studentGroupId, Ent.USER, '']
|
|
51608
|
+
kwargs = {'courseId': courseId, 'studentGroupId': studentGroupId, 'body': {'userId': ''}}
|
|
51609
|
+
for student in students:
|
|
51610
|
+
i += 1
|
|
51611
|
+
if getUserIds:
|
|
51612
|
+
userId = _getStudentUserId(kvList, student, i, count)
|
|
51613
|
+
if userId is None:
|
|
51614
|
+
continue
|
|
51615
|
+
kvList[-1] = student
|
|
51616
|
+
else:
|
|
51617
|
+
userId = student
|
|
51618
|
+
kvList[-1] = convertUIDtoEmailAddress(f"id:{userId}", cd=cd, emailTypes=['user'])
|
|
51619
|
+
kwargs['body']['userId'] = userId
|
|
51620
|
+
_processStudent('create', kvList, kwargs, i, count)
|
|
51621
|
+
|
|
51622
|
+
def _removeStudents(students, getUserIds):
|
|
51623
|
+
count = len(students)
|
|
51624
|
+
i = 0
|
|
51625
|
+
entityPerformActionNumItems([Ent.COURSE, courseId, Ent.COURSE_STUDENTGROUP, studentGroupId], count, Ent.USER)
|
|
51626
|
+
kvList = [Ent.COURSE, courseId, Ent.COURSE_STUDENTGROUP, studentGroupId, Ent.USER, '']
|
|
51627
|
+
kwargs = {'courseId': courseId, 'studentGroupId': studentGroupId, 'userId': ''}
|
|
51628
|
+
for student in students:
|
|
51629
|
+
i += 1
|
|
51630
|
+
if getUserIds:
|
|
51631
|
+
userId = _getStudentUserId(kvList, student, i, count)
|
|
51632
|
+
if userId is None:
|
|
51633
|
+
continue
|
|
51634
|
+
kvList[-1] = student
|
|
51635
|
+
else:
|
|
51636
|
+
userId = student
|
|
51637
|
+
kvList[-1] = convertUIDtoEmailAddress(f"id:{userId}", cd=cd, emailTypes=['user'])
|
|
51638
|
+
kwargs['userId'] = userId
|
|
51639
|
+
_processStudent('delete', kvList, kwargs, i, count)
|
|
51640
|
+
|
|
51641
|
+
croom = buildGAPIObject(API.CLASSROOM)
|
|
51642
|
+
cd = buildGAPIObject(API.DIRECTORY)
|
|
51643
|
+
action = Act.Get()
|
|
51644
|
+
courseId = getString(Cmd.OB_COURSE_ID)
|
|
51645
|
+
studentGroupId = getString(Cmd.OB_STUDENTGROUP_ID)
|
|
51646
|
+
if action != Act.CLEAR:
|
|
51647
|
+
_, clStudents = getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS, groupMemberType=Ent.TYPE_USER)
|
|
51648
|
+
clStudents = [normalizeEmailAddressOrUID(student) for student in clStudents]
|
|
51649
|
+
checkForExtraneousArguments()
|
|
51650
|
+
_, count, coursesInfo = _getCoursesOwnerInfo(croom, [courseId], GC.Values[GC.USE_COURSE_OWNER_ACCESS])
|
|
51651
|
+
if count == 0:
|
|
51652
|
+
return
|
|
51653
|
+
ocroom = coursesInfo[courseId]['croom']
|
|
51654
|
+
courseId = coursesInfo[courseId]['id']
|
|
51655
|
+
if action in {Act.SYNC, Act.CLEAR}:
|
|
51656
|
+
currentStudents = [student['userId'] for student in _getCurrentStudents()]
|
|
51657
|
+
if action == Act.CLEAR:
|
|
51658
|
+
_removeStudents(currentStudents, False)
|
|
51659
|
+
elif action == Act.DELETE:
|
|
51660
|
+
_removeStudents(clStudents, True)
|
|
51661
|
+
elif action in {Act.ADD, Act.CREATE}:
|
|
51662
|
+
_addStudents(clStudents, True)
|
|
51663
|
+
else: # elif action == Act.SYNC:
|
|
51664
|
+
currentMembersSet = set(currentStudents)
|
|
51665
|
+
syncMembersSet = set()
|
|
51666
|
+
count = len(clStudents)
|
|
51667
|
+
i = 0
|
|
51668
|
+
kvList = [Ent.COURSE, courseId, Ent.COURSE_STUDENTGROUP, studentGroupId, Ent.USER, '']
|
|
51669
|
+
for student in clStudents:
|
|
51670
|
+
i += 1
|
|
51671
|
+
kvList[-1] = student
|
|
51672
|
+
userId = _getStudentUserId(kvList, student, i, count)
|
|
51673
|
+
if userId is None:
|
|
51674
|
+
continue
|
|
51675
|
+
syncMembersSet.add(userId)
|
|
51676
|
+
removeStudentsSet = currentMembersSet-syncMembersSet
|
|
51677
|
+
addStudentsSet = syncMembersSet-currentMembersSet
|
|
51678
|
+
Act.Set(Act.DELETE)
|
|
51679
|
+
_removeStudents(removeStudentsSet, False)
|
|
51680
|
+
Act.Set(Act.ADD)
|
|
51681
|
+
_addStudents(addStudentsSet, False)
|
|
51682
|
+
|
|
51683
|
+
# gam print course-studentgroup-members [todrive <ToDriveAttribute>*]
|
|
51684
|
+
# (course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] [states <CourseStateList>])
|
|
51685
|
+
# [showitemcountonly] [formatjson [quotechar <Character>]]
|
|
51686
|
+
def doPrintCourseStudentGroupMembers():
|
|
51687
|
+
doPrintCourseStudentGroups(showMembers=True)
|
|
51688
|
+
|
|
51212
51689
|
def _showASPs(user, asps, i=0, count=0):
|
|
51213
51690
|
Act.Set(Act.SHOW)
|
|
51214
51691
|
jcount = len(asps)
|
|
@@ -77337,6 +77814,8 @@ MAIN_ADD_CREATE_FUNCTIONS = {
|
|
|
77337
77814
|
Cmd.ARG_CIGROUP: doCreateCIGroup,
|
|
77338
77815
|
Cmd.ARG_CONTACT: doCreateDomainContact,
|
|
77339
77816
|
Cmd.ARG_COURSE: doCreateCourse,
|
|
77817
|
+
Cmd.ARG_COURSESTUDENTGROUP: doCreateCourseStudentGroups,
|
|
77818
|
+
Cmd.ARG_COURSESTUDENTGROUPMEMBERS: doProcessCourseStudentGroupMembers,
|
|
77340
77819
|
Cmd.ARG_DATATRANSFER: doCreateDataTransfer,
|
|
77341
77820
|
Cmd.ARG_DEVICE: doCreateCIDevice,
|
|
77342
77821
|
Cmd.ARG_DOMAIN: doCreateDomain,
|
|
@@ -77412,6 +77891,8 @@ MAIN_COMMANDS_WITH_OBJECTS = {
|
|
|
77412
77891
|
(Act.CLEAR,
|
|
77413
77892
|
{Cmd.ARG_ALERTSETTINGS: doClearAlertSettings,
|
|
77414
77893
|
Cmd.ARG_CONTACT: doClearDomainContacts,
|
|
77894
|
+
Cmd.ARG_COURSESTUDENTGROUP: doClearCourseStudentGroups,
|
|
77895
|
+
Cmd.ARG_COURSESTUDENTGROUPMEMBERS: doProcessCourseStudentGroupMembers,
|
|
77415
77896
|
}
|
|
77416
77897
|
),
|
|
77417
77898
|
'close':
|
|
@@ -77454,6 +77935,8 @@ MAIN_COMMANDS_WITH_OBJECTS = {
|
|
|
77454
77935
|
Cmd.ARG_CONTACTPHOTO: doDeleteDomainContactPhoto,
|
|
77455
77936
|
Cmd.ARG_COURSE: doDeleteCourse,
|
|
77456
77937
|
Cmd.ARG_COURSES: doDeleteCourses,
|
|
77938
|
+
Cmd.ARG_COURSESTUDENTGROUP: doDeleteCourseStudentGroups,
|
|
77939
|
+
Cmd.ARG_COURSESTUDENTGROUPMEMBERS: doProcessCourseStudentGroupMembers,
|
|
77457
77940
|
Cmd.ARG_DEVICE: doDeleteCIDevice,
|
|
77458
77941
|
Cmd.ARG_DEVICEUSER: doDeleteCIDeviceUser,
|
|
77459
77942
|
Cmd.ARG_DOMAIN: doDeleteDomain,
|
|
@@ -77631,6 +78114,8 @@ MAIN_COMMANDS_WITH_OBJECTS = {
|
|
|
77631
78114
|
Cmd.ARG_COURSEANNOUNCEMENTS: doPrintCourseAnnouncements,
|
|
77632
78115
|
Cmd.ARG_COURSEMATERIALS: doPrintCourseMaterials,
|
|
77633
78116
|
Cmd.ARG_COURSEPARTICIPANTS: doPrintCourseParticipants,
|
|
78117
|
+
Cmd.ARG_COURSESTUDENTGROUP: doPrintCourseStudentGroups,
|
|
78118
|
+
Cmd.ARG_COURSESTUDENTGROUPMEMBERS: doPrintCourseStudentGroupMembers,
|
|
77634
78119
|
Cmd.ARG_COURSESUBMISSIONS: doPrintCourseSubmissions,
|
|
77635
78120
|
Cmd.ARG_COURSETOPICS: doPrintCourseTopics,
|
|
77636
78121
|
Cmd.ARG_COURSEWORK: doPrintCourseWork,
|
|
@@ -77815,6 +78300,7 @@ MAIN_COMMANDS_WITH_OBJECTS = {
|
|
|
77815
78300
|
(Act.SYNC,
|
|
77816
78301
|
{Cmd.ARG_DEVICE: doSyncCIDevices,
|
|
77817
78302
|
Cmd.ARG_SHAREDDRIVEACLS: copySyncSharedDriveACLs,
|
|
78303
|
+
Cmd.ARG_COURSESTUDENTGROUPMEMBERS: doProcessCourseStudentGroupMembers,
|
|
77818
78304
|
}
|
|
77819
78305
|
),
|
|
77820
78306
|
'unhide':
|
|
@@ -77837,6 +78323,7 @@ MAIN_COMMANDS_WITH_OBJECTS = {
|
|
|
77837
78323
|
Cmd.ARG_CONTACTPHOTO: doUpdateDomainContactPhoto,
|
|
77838
78324
|
Cmd.ARG_COURSE: doUpdateCourse,
|
|
77839
78325
|
Cmd.ARG_COURSES: doUpdateCourses,
|
|
78326
|
+
Cmd.ARG_COURSESTUDENTGROUP: doUpdateCourseStudentGroups,
|
|
77840
78327
|
Cmd.ARG_CROS: doUpdateCrOSDevices,
|
|
77841
78328
|
Cmd.ARG_CUSTOMER: doUpdateCustomer,
|
|
77842
78329
|
Cmd.ARG_DEVICE: doUpdateCIDevice,
|
|
@@ -77954,6 +78441,7 @@ MAIN_COMMANDS_OBJ_ALIASES = {
|
|
|
77954
78441
|
Cmd.ARG_CLASSROOMINVITATIONS: Cmd.ARG_CLASSROOMINVITATION,
|
|
77955
78442
|
Cmd.ARG_CONTACTS: Cmd.ARG_CONTACT,
|
|
77956
78443
|
Cmd.ARG_CONTACTPHOTOS: Cmd.ARG_CONTACTPHOTO,
|
|
78444
|
+
Cmd.ARG_COURSESTUDENTGROUPS: Cmd.ARG_COURSESTUDENTGROUP,
|
|
77957
78445
|
Cmd.ARG_CROSES: Cmd.ARG_CROS,
|
|
77958
78446
|
Cmd.ARG_DATATRANSFERS: Cmd.ARG_DATATRANSFER,
|
|
77959
78447
|
Cmd.ARG_DEVICES: Cmd.ARG_DEVICE,
|
gam/gamlib/glcfg.py
CHANGED
|
@@ -145,6 +145,8 @@ CSV_OUTPUT_USERS_AUDIT = 'csv_output_users_audit'
|
|
|
145
145
|
CUSTOMER_ID = 'customer_id'
|
|
146
146
|
# If debug_level > 0: extra_args['prettyPrint'] = True, httplib2.debuglevel = gam_debug_level, appsObj.debug = True
|
|
147
147
|
DEBUG_LEVEL = 'debug_level'
|
|
148
|
+
# Developer Preview API Key
|
|
149
|
+
DEVELOPER_PREVIEW_API_KEY = 'developer_preview_api_key'
|
|
148
150
|
# When retrieving lists of ChromeOS devices from API, how many should be retrieved in each chunk
|
|
149
151
|
DEVICE_MAX_RESULTS = 'device_max_results'
|
|
150
152
|
# Domain obtained from gam.cfg or oauth2.txt
|
|
@@ -370,6 +372,7 @@ Defaults = {
|
|
|
370
372
|
CSV_OUTPUT_USERS_AUDIT: FALSE,
|
|
371
373
|
CUSTOMER_ID: MY_CUSTOMER,
|
|
372
374
|
DEBUG_LEVEL: '0',
|
|
375
|
+
DEVELOPER_PREVIEW_API_KEY: '',
|
|
373
376
|
DEVICE_MAX_RESULTS: '200',
|
|
374
377
|
DOMAIN: '',
|
|
375
378
|
DRIVE_DIR: '',
|
|
@@ -536,6 +539,7 @@ VAR_INFO = {
|
|
|
536
539
|
CSV_OUTPUT_USERS_AUDIT: {VAR_TYPE: TYPE_BOOLEAN},
|
|
537
540
|
CUSTOMER_ID: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'CUSTOMER_ID', VAR_LIMITS: (0, None)},
|
|
538
541
|
DEBUG_LEVEL: {VAR_TYPE: TYPE_INTEGER, VAR_SIGFILE: 'debug.gam', VAR_LIMITS: (0, None), VAR_SFFT: ('0', '4')},
|
|
542
|
+
DEVELOPER_PREVIEW_API_KEY: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
|
|
539
543
|
DEVICE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 200)},
|
|
540
544
|
DOMAIN: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'GA_DOMAIN', VAR_LIMITS: (0, None)},
|
|
541
545
|
DRIVE_DIR: {VAR_TYPE: TYPE_DIRECTORY, VAR_ENVVAR: 'GAMDRIVEDIR'},
|
gam/gamlib/glclargs.py
CHANGED
|
@@ -528,6 +528,9 @@ class GamCLArgs():
|
|
|
528
528
|
ARG_COURSEANNOUNCEMENTS = 'courseannouncements'
|
|
529
529
|
ARG_COURSEMATERIALS = 'coursematerials'
|
|
530
530
|
ARG_COURSEPARTICIPANTS = 'courseparticipants'
|
|
531
|
+
ARG_COURSESTUDENTGROUP = 'coursestudentgroup'
|
|
532
|
+
ARG_COURSESTUDENTGROUPS = 'coursestudentgroups'
|
|
533
|
+
ARG_COURSESTUDENTGROUPMEMBERS = 'coursestudentgroupmembers'
|
|
531
534
|
ARG_COURSESUBMISSIONS = 'coursesubmissions'
|
|
532
535
|
ARG_COURSETOPICS = 'coursetopics'
|
|
533
536
|
ARG_COURSEWORK = 'coursework'
|
|
@@ -1055,6 +1058,8 @@ class GamCLArgs():
|
|
|
1055
1058
|
OB_STATE_NAME_LIST = "StateNameList"
|
|
1056
1059
|
OB_STRING = 'String'
|
|
1057
1060
|
OB_STRING_LIST = 'StringList'
|
|
1061
|
+
OB_STUDENTGROUP_ID = 'StudentGroupID'
|
|
1062
|
+
OB_STUDENTGROUP_ID_ENTITY = 'StudentGroupIDEntity'
|
|
1058
1063
|
OB_STUDENT_ITEM = 'StudentItem'
|
|
1059
1064
|
OB_TAG = 'Tag'
|
|
1060
1065
|
OB_TAGMANAGER_PATH_LIST = 'TagManagerPathList'
|
gam/gamlib/glentity.py
CHANGED
|
@@ -155,6 +155,8 @@ class GamEntity():
|
|
|
155
155
|
COURSE_MATERIAL_STATE = 'cmst'
|
|
156
156
|
COURSE_NAME = 'cona'
|
|
157
157
|
COURSE_STATE = 'cost'
|
|
158
|
+
COURSE_STUDENTGROUP = 'cosg'
|
|
159
|
+
COURSE_STUDENTGROUP_MEMBER = 'csgm'
|
|
158
160
|
COURSE_SUBMISSION_ID = 'csid'
|
|
159
161
|
COURSE_SUBMISSION_STATE = 'csst'
|
|
160
162
|
COURSE_TOPIC = 'ctop'
|
|
@@ -517,6 +519,8 @@ class GamEntity():
|
|
|
517
519
|
COURSE_MATERIAL_STATE: ['Course Material States', 'Course Material State'],
|
|
518
520
|
COURSE_NAME: ['Course Names', 'Course Name'],
|
|
519
521
|
COURSE_STATE: ['Course States', 'Course State'],
|
|
522
|
+
COURSE_STUDENTGROUP: ['Course Student Groups', 'Course Student Group'],
|
|
523
|
+
COURSE_STUDENTGROUP_MEMBER: ['Course Student Group Members', 'Course Student Group Member'],
|
|
520
524
|
COURSE_SUBMISSION_ID: ['Course Submission IDs', 'Course Submission ID'],
|
|
521
525
|
COURSE_SUBMISSION_STATE: ['Course Submission States', 'Course Submission State'],
|
|
522
526
|
COURSE_TOPIC: ['Course Topics', 'Course Topic'],
|
gam/gamlib/glglobals.py
CHANGED
|
@@ -31,6 +31,8 @@ API_CALLS_RETRY_DATA = 'rtry'
|
|
|
31
31
|
CACHE_DIR = 'gacd'
|
|
32
32
|
# Reset GAM cache directory after discovery
|
|
33
33
|
CACHE_DISCOVERY_ONLY = 'gcdo'
|
|
34
|
+
# Classroom owner service object
|
|
35
|
+
CLASSROOM_OWNER_SA = 'cosa'
|
|
34
36
|
# Classroom service not available
|
|
35
37
|
CLASSROOM_SERVICE_NOT_AVAILABLE = 'csna'
|
|
36
38
|
# Command logging
|
|
@@ -221,6 +223,7 @@ Globals = {
|
|
|
221
223
|
API_CALLS_RETRY_DATA: {},
|
|
222
224
|
CACHE_DIR: None,
|
|
223
225
|
CACHE_DISCOVERY_ONLY: True,
|
|
226
|
+
CLASSROOM_OWNER_SA: {},
|
|
224
227
|
CLASSROOM_SERVICE_NOT_AVAILABLE: False,
|
|
225
228
|
CMDLOG_HANDLER: None,
|
|
226
229
|
CMDLOG_LOGGER: None,
|
gam/gamlib/glmsgs.py
CHANGED
|
@@ -53,7 +53,7 @@ Please go to:
|
|
|
53
53
|
5. Click "NEXT"
|
|
54
54
|
6. Under "Audience", choose INTERNAL
|
|
55
55
|
7. Click "NEXT"
|
|
56
|
-
8. Under, "Contact Information", enter
|
|
56
|
+
8. Under, "Contact Information", enter {2} or another value in "Email addresses *"
|
|
57
57
|
9. Click "NEXT"
|
|
58
58
|
10. Under "Finish", click "I agree to the Google API Services: User Data Policy."
|
|
59
59
|
11. Click "CONTINUE"
|
gam/googleapiclient/version.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
gam/__init__.py,sha256=
|
|
1
|
+
gam/__init__.py,sha256=sa-yzi7R7kgKEULVunOY9AKzQbWAZfX9XH3tRPwGefg,3608416
|
|
2
2
|
gam/__main__.py,sha256=amz0-959ph6zkZKqjaar4n60yho-T37w6qWI36qx0CA,1049
|
|
3
3
|
gam/cacerts.pem,sha256=DUsVo2XlFYwfkhe3gnxa-Km4Z4noz74hSApXwTT-nQE,44344
|
|
4
4
|
gam/cbcm-v1.1beta1.json,sha256=xO5XloCQQULmPbFBx5bckdqmbLFQ7sJ2TImhE1ysDIY,19439
|
|
@@ -24,14 +24,14 @@ gam/atom/url.py,sha256=pxO1TlORxyKQTQ1bkBE1unFzjnv9c8LjJkm-UEORShY,4276
|
|
|
24
24
|
gam/gamlib/__init__.py,sha256=z5mF-y0j8pm-YNFBaiuxB4M_GAUPG-cXWwrhYwrVReM,679
|
|
25
25
|
gam/gamlib/glaction.py,sha256=1Il_HrChVnPkzZwiZs5au4mFQVtq4K1Z42uIuR6qdnI,9419
|
|
26
26
|
gam/gamlib/glapi.py,sha256=u97M7Y2BeP3tYEEGYEz-9kY4fdV0fYkeqC3YN-sRwNc,36028
|
|
27
|
-
gam/gamlib/glcfg.py,sha256=
|
|
28
|
-
gam/gamlib/glclargs.py,sha256=
|
|
29
|
-
gam/gamlib/glentity.py,sha256=
|
|
27
|
+
gam/gamlib/glcfg.py,sha256=7Ut-7sDTw-WVHZfvDWn_dlVNfuWd6VsPDBpQ3qnyzJE,28100
|
|
28
|
+
gam/gamlib/glclargs.py,sha256=9Oze97BT_GS2WXf4LYg4JlSCmZ_8fG2a33Ft1_pX43k,44134
|
|
29
|
+
gam/gamlib/glentity.py,sha256=8F98YR1ronheiQShD6WHlY-YnBKfMDrc33iRuRoLIvo,35097
|
|
30
30
|
gam/gamlib/glgapi.py,sha256=pdBbwNtnCwFWxJGaP-_3hdTjSNoOCJF2yo76WdQOi1k,40426
|
|
31
31
|
gam/gamlib/glgdata.py,sha256=weRppttWm6uRyqtBoGPKoHiNZ2h28nhfUV4J_mbCszY,2707
|
|
32
|
-
gam/gamlib/glglobals.py,sha256=
|
|
32
|
+
gam/gamlib/glglobals.py,sha256=oJfaLUQj46XqwrOzRfWhGqO0f1P26xjJZefaILJUFGE,9695
|
|
33
33
|
gam/gamlib/glindent.py,sha256=RfBa2LDfLIqPLL5vMfC689TCVmqn8xf-qulSzkiatrc,1228
|
|
34
|
-
gam/gamlib/glmsgs.py,sha256=
|
|
34
|
+
gam/gamlib/glmsgs.py,sha256=uluaFxw5YCG1so9uvOYU6HvAwGJNqJcB1curD8hH-G0,34001
|
|
35
35
|
gam/gamlib/glskus.py,sha256=e1u3zw1MGQjBgAFXqjrGWQl2d7eYpVlMYGpIKNwjskQ,15360
|
|
36
36
|
gam/gamlib/gluprop.py,sha256=IyPLCyvn7-NHTUenM71YPQPXRZXx6CB5q-GtJ-FYd1c,11461
|
|
37
37
|
gam/gamlib/glverlibs.py,sha256=xoQXiwcE_-HVYKv-VYA8O0mazRsc9mN-_ysj1dAlMyc,992
|
|
@@ -58,15 +58,15 @@ gam/googleapiclient/http.py,sha256=ITE51oqDBqN1-AA5D-Tnlj3egGc_5O0V5xSzBw3UTKI,6
|
|
|
58
58
|
gam/googleapiclient/mimeparse.py,sha256=wwouQMCjppTocJtiQhkkTa27kocYwlFRALL2z11Xo1Y,6530
|
|
59
59
|
gam/googleapiclient/model.py,sha256=NQDO1GhOGNVCJlSSCLOecdA11yf8RDXfSLFxYb3R7EE,14085
|
|
60
60
|
gam/googleapiclient/schema.py,sha256=rR3u8WPQ_V8a7GCUsNuvtf6GxzwuMO0HaqsTBp3tnyM,10414
|
|
61
|
-
gam/googleapiclient/version.py,sha256=
|
|
61
|
+
gam/googleapiclient/version.py,sha256=CQnalMsxpdK1_gw_iADQK3D0RNBQ2vMlzw3PbyNFWC4,599
|
|
62
62
|
gam/googleapiclient/discovery_cache/__init__.py,sha256=ww_vl0vhVLuHSEdRTv3-gq6EDG--Ff7rILYHHFifnzc,2315
|
|
63
63
|
gam/googleapiclient/discovery_cache/appengine_memcache.py,sha256=6T1pQj-toAhDwfgLuiggFGhxKNGw5y-NnLUzLIF_M4s,1657
|
|
64
64
|
gam/googleapiclient/discovery_cache/base.py,sha256=yCDPtxnbNN-p5_9fzBacC6P3wcUPlaCQIy5v_dXTons,1389
|
|
65
65
|
gam/googleapiclient/discovery_cache/file_cache.py,sha256=sim3Mg4HgRYo3vX75jvcKy_aV568EvIrtBfvfbw-044,4774
|
|
66
66
|
gam/iso8601/__init__.py,sha256=Z2PsYbXgAH5a5xzUvgczCboPzqWpm65kRcIngCnhViU,1218
|
|
67
67
|
gam/iso8601/iso8601.py,sha256=Li2FHZ4sBTWuthuQhyCvmvj0j6At8JbGzkSv2fc2RHU,4384
|
|
68
|
-
gam7-7.
|
|
69
|
-
gam7-7.
|
|
70
|
-
gam7-7.
|
|
71
|
-
gam7-7.
|
|
72
|
-
gam7-7.
|
|
68
|
+
gam7-7.20.1.dist-info/METADATA,sha256=7C53COsDbo2DNmBB177TsMQBp3Y_fgnMnx88aqQXuHg,2940
|
|
69
|
+
gam7-7.20.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
70
|
+
gam7-7.20.1.dist-info/entry_points.txt,sha256=HVUM5J7dA8YwvJfG30jiLefR19ExMs387TWugWd9sf4,42
|
|
71
|
+
gam7-7.20.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
72
|
+
gam7-7.20.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|