print filecounts addcsvdata; course copyfrom updates
Some checks are pending
Build and test GAM / build (Win64, build, 8, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 2, linux-aarch64, [self-hosted linux arm64]) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, [self-hosted linux arm64], yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (universal2, build, 7, darwin64-arm64 darwin64-x86_64, macos-14) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-20.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 3, linux-x86_64, ubuntu-20.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, darwin64-x86_64, macos-12) (push) Waiting to run
Build and test GAM / build (x86_64, test, 10, ubuntu-22.04, 3.9) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-22.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-22.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 9, ubuntu-22.04, 3.8) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run

This commit is contained in:
Ross Scroggs
2024-08-13 19:54:49 -07:00
parent 8db7e32bd2
commit e80ed0e700
9 changed files with 144 additions and 38 deletions

View File

@@ -134,6 +134,7 @@ gam user user@domain.com check|update serviceaccount
creationtime| creationtime|
creator|creatoruserid| creator|creatoruserid|
id| id|
individualstudentsoptions|
materials| materials|
scheduledtime| scheduledtime|
state| state|
@@ -154,6 +155,7 @@ gam user user@domain.com check|update serviceaccount
creator|creatoruserid| creator|creatoruserid|
description| description|
id| id|
individualstudentsoptions|
materials| materials|
scheduledtime| scheduledtime|
state| state|
@@ -179,6 +181,7 @@ gam user user@domain.com check|update serviceaccount
duedate| duedate|
duetime| duetime|
id| id|
individualstudentsoptions|
materials| materials|
maxpoints| maxpoints|
scheduledtime| scheduledtime|
@@ -187,6 +190,7 @@ gam user user@domain.com check|update serviceaccount
title| title|
topicid| topicid|
updatetime| updatetime|
workid|
worktype worktype
<CourseWorkFieldNameList> ::= "<CourseWorkFieldName>(,<CourseWorkFieldName>)*" <CourseWorkFieldNameList> ::= "<CourseWorkFieldName>(,<CourseWorkFieldName>)*"
@@ -270,7 +274,9 @@ The options `name <String>` and `teacher <UserItem>` are required when creating
gam create|add course [id|alias <CourseAlias>] <CourseAttribute>* gam create|add course [id|alias <CourseAlias>] <CourseAttribute>*
[copyfrom <CourseID> [copyfrom <CourseID>
[announcementstates <CourseAnnouncementStateList>] [announcementstates <CourseAnnouncementStateList>]
[individualstudentannouncements copy|delete|maptoall]
[materialstates <CourseMaterialStateList>] [materialstates <CourseMaterialStateList>]
[individualstudentmaterials copy|delete|maptoall]
[workstates <CourseWorkStateList>] [workstates <CourseWorkStateList>]
[individualstudentassignments copy|delete|maptoall] [individualstudentassignments copy|delete|maptoall]
[removeduedate [<Boolean>]] [removeduedate [<Boolean>]]
@@ -285,7 +291,9 @@ gam create|add course [id|alias <CourseAlias>] <CourseAttribute>*
gam update course <CourseID> <CourseAttribute>+ gam update course <CourseID> <CourseAttribute>+
[copyfrom <CourseID> [copyfrom <CourseID>
[announcementstates <CourseAnnouncementStateList>] [announcementstates <CourseAnnouncementStateList>]
[individualstudentannouncements copy|delete|maptoall]
[materialstates <CourseMaterialStateList>] [materialstates <CourseMaterialStateList>]
[individualstudentmaterials copy|delete|maptoall]
[workstates <CourseWorkStateList>] [workstates <CourseWorkStateList>]
[individualstudentassignments copy|delete|maptoall] [individualstudentassignments copy|delete|maptoall]
[removeduedate [<Boolean>]] [removeduedate [<Boolean>]]
@@ -299,7 +307,9 @@ gam update course <CourseID> <CourseAttribute>+
gam update courses <CourseEntity> <CourseAttribute>+ gam update courses <CourseEntity> <CourseAttribute>+
[copyfrom <CourseID> [copyfrom <CourseID>
[announcementstates <CourseAnnouncementStateList>] [announcementstates <CourseAnnouncementStateList>]
[individualstudentannouncements copy|delete|maptoall]
[materialstates <CourseMaterialStateList>] [materialstates <CourseMaterialStateList>]
[individualstudentmaterials copy|delete|maptoall]
[workstates <CourseWorkStateList>] [workstates <CourseWorkStateList>]
[individualstudentassignments copy|delete|maptoall] [individualstudentassignments copy|delete|maptoall]
[removeduedate [<Boolean>]] [removeduedate [<Boolean>]]
@@ -314,11 +324,17 @@ gam update courses <CourseEntity> <CourseAttribute>+
`copyfrom <CourseID>` allows copying of course announcements, work, topics and members from one course to another. `copyfrom <CourseID>` allows copying of course announcements, work, topics and members from one course to another.
* Accouncements - By default, no course announcements are copied * Accouncements - By default, no course announcements are copied
* `announcementstates <CourseAnnouncementStateList>` - Copy class announcements with the specified states * `announcementstates <CourseAnnouncementStateList>` - Copy class announcements with the specified states
* `individualstudentannouncements copy` - Copy individual student announcements; this is the default. You will get an error if a student is not a member of the course
* `individualstudentannouncements delete` - Delete individual student announcements
* `individualstudentannouncements maptoall` - Map individual student announcements to all student announcements
* Materials - By default, no course materials are copied * Materials - By default, no course materials are copied
* `materialstates <CourseMaterialsStateList>` - Copy class materials with the specified states * `materialstates <CourseMaterialsStateList>` - Copy class materials with the specified states
* `individualstudentmaterials copy` - Copy individual student materials; this is the default. You will get an error if a student is not a member of the course
* `individualstudentmaterials delete` - Delete individual student materials
* `individualstudentmaterials maptoall` - Map individual student materials to all student materials
* Work - By default, no course work is copied * Work - By default, no course work is copied
* `workstates <CourseWorkStateList>` - Copy class work with the specified states * `workstates <CourseWorkStateList>` - Copy class work with the specified states
* `individualstudentassignments copy` - Copy individual student assignments; this is the default. You will get an error if the student is not a member of the course. * `individualstudentassignments copy` - Copy individual student assignments; this is the default. You will get an error if the student is not a member of the course
* `individualstudentassignments delete` - Delete individual student assignments * `individualstudentassignments delete` - Delete individual student assignments
* `individualstudentassignments maptoall` - Map individual student assignments to all student assignments * `individualstudentassignments maptoall` - Map individual student assignments to all student assignments
* `removeduedate false` - Remove due dates before the current time; this is the default * `removeduedate false` - Remove due dates before the current time; this is the default

View File

@@ -78,7 +78,7 @@
<SharedDriveID> ::= <String> <SharedDriveID> ::= <String>
<SharedDriveName> ::= <String> <SharedDriveName> ::= <String>
<SharedDriveIDEntity> ::= (teamdriveid <DriveFileItem>) | (teamdriveid:<DriveFileItem>) <SharedDriveIDEntity> ::= (teamdriveid <SharedDriveID>) | (teamdriveid:<SharedDriveID>)
<SharedDriveNameEntity> ::= (teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>) <SharedDriveNameEntity> ::= (teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
<SharedDriveFileNameEntity> ::= (teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>) <SharedDriveFileNameEntity> ::= (teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>)

View File

@@ -10,6 +10,20 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
See [Downloads-Installs](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads-Installs) for Windows or other options, including manual installation See [Downloads-Installs](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads-Installs) for Windows or other options, including manual installation
### 6.80.02
Added option `addcsvdata <FieldName> <String>` to `gam <UserTypeEntity> print filecounts` that adds
additional columns of data to the CSV file output.
Added options `individualstudentannouncements copy|delete|maptoall` and `individualstudentmaterials copy|delete|maptoall`
to `gam create|update course ... copyfrom` that controls how individual student announcements and materials in the `copyfrom` course are processed.
* `individualstudentannouncements copy` - Copy individual student announcements; this is the default. You will get an error if a student is not a member of the course
* `individualstudentannouncements delete` - Delete individual student announcements
* `individualstudentannouncements maptoall` - Map individual student announcements to all student announcements
* `individualstudentmaterials copy` - Copy individual student materials; this is the default. You will get an error if a student is not a member of the course
* `individualstudentmaterials delete` - Delete individual student materials
* `individualstudentmaterials maptoall` - Map individual student materials to all student materials
### 6.80.01 ### 6.80.01
Added options `showstudentsaslist [<Boolean>]` and `delimiter <Character>` to `gam print course-work`. Added options `showstudentsaslist [<Boolean>]` and `delimiter <Character>` to `gam print course-work`.

View File

@@ -251,7 +251,7 @@ writes the credentials into the file oauth2.txt.
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin$ gam version admin@server:/Users/admin$ gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAMADV-XTD3 6.80.01 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.80.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final Python 3.12.4 64-bit final
MacOS Sonoma 14.5 x86_64 MacOS Sonoma 14.5 x86_64
@@ -923,7 +923,7 @@ writes the credentials into the file oauth2.txt.
C:\>del C:\GAMConfig\oauth2.txt C:\>del C:\GAMConfig\oauth2.txt
C:\>gam version C:\>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAMADV-XTD3 6.80.01 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.80.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final Python 3.12.4 64-bit final
Windows-10-10.0.17134 AMD64 Windows-10-10.0.17134 AMD64

View File

@@ -55,6 +55,16 @@
never| never|
now|today now|today
<SharedDriveID> ::= <String>
<SharedDriveName> ::= <String>
<SharedDriveIDEntity> ::= (teamdriveid <SharedDriveID>) | (teamdriveid:<SharedDriveID>)
<SharedDriveNameEntity> ::= (teamdrive <SharedDriveName>) | (teamdrive:<SharedDriveName>)
<SharedDriveFileNameEntity> ::= (teamdrivefilename <DriveFileName>) | (teamdrivefilename:<DriveFileName>)
<SharedDriveEntity> ::=
<SharedDriveIDEntity> |
<SharedDriveNameEntity>
<MimeTypeShortcut> ::= <MimeTypeShortcut> ::=
gdoc|gdocument| gdoc|gdocument|
gdrawing| gdrawing|
@@ -669,7 +679,7 @@ gam <UserTypeEntity> print filecounts [todrive <ToDriveAttribute>*]
[filenamematchpattern <RegularExpression>] [filenamematchpattern <RegularExpression>]
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>] <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
[excludetrashed] [excludetrashed]
[showsize] [showmimetypesize] [showsize] [showmimetypesize] (addcsvdata <FieldName> <String>)*
[summary none|only|plus] [summaryuser <String>] [summary none|only|plus] [summaryuser <String>]
gam <UserTypeEntity> show filecounts gam <UserTypeEntity> show filecounts
[((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>) [((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>)
@@ -692,6 +702,9 @@ The `showsize` option displays the total size (in bytes) of the files counted.
The showmimetypesize' displays the total size (in bytes) of each MIME type counted. The showmimetypesize' displays the total size (in bytes) of each MIME type counted.
For print filecouts, add additional columns of data from the command line to the output:
* `addcsvdata <FieldName> <String>` - Add additional columns of data from the command line to the output
See [Select files for Display file counts, list, tree](#select-files-for-display-file-counts-list-tree) See [Select files for Display file counts, list, tree](#select-files-for-display-file-counts-list-tree)
Use the `excludetrashed` option to suppress counting files in the trash. Use the `excludetrashed` option to suppress counting files in the trash.

View File

@@ -3,7 +3,7 @@
Print the current version of Gam with details Print the current version of Gam with details
``` ```
gam version gam version
GAMADV-XTD3 6.80.01 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.80.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final Python 3.12.4 64-bit final
MacOS Sonoma 14.5 x86_64 MacOS Sonoma 14.5 x86_64
@@ -15,7 +15,7 @@ Time: 2023-06-02T21:10:00-07:00
Print the current version of Gam with details and time offset information Print the current version of Gam with details and time offset information
``` ```
gam version timeoffset gam version timeoffset
GAMADV-XTD3 6.80.01 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.80.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final Python 3.12.4 64-bit final
MacOS Sonoma 14.5 x86_64 MacOS Sonoma 14.5 x86_64
@@ -27,7 +27,7 @@ Your system time differs from www.googleapis.com by less than 1 second
Print the current version of Gam with extended details and SSL information Print the current version of Gam with extended details and SSL information
``` ```
gam version extended gam version extended
GAMADV-XTD3 6.80.01 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.80.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final Python 3.12.4 64-bit final
MacOS Sonoma 14.5 x86_64 MacOS Sonoma 14.5 x86_64
@@ -64,7 +64,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3 Path: /Users/Admin/bin/gamadv-xtd3
Version Check: Version Check:
Current: 5.35.08 Current: 5.35.08
Latest: 6.80.01 Latest: 6.80.02
echo $? echo $?
1 1
``` ```
@@ -72,7 +72,7 @@ echo $?
Print the current version number without details Print the current version number without details
``` ```
gam version simple gam version simple
6.80.01 6.80.02
``` ```
In Linux/MacOS you can do: In Linux/MacOS you can do:
``` ```
@@ -82,7 +82,7 @@ echo $VER
Print the current version of Gam and address of this Wiki Print the current version of Gam and address of this Wiki
``` ```
gam help gam help
GAM 6.80.01 - https://github.com/taers232c/GAMADV-XTD3 GAM 6.80.02 - https://github.com/taers232c/GAMADV-XTD3
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.4 64-bit final Python 3.12.4 64-bit final
MacOS Sonoma 14.5 x86_64 MacOS Sonoma 14.5 x86_64

View File

@@ -2939,44 +2939,55 @@ gam <UserTypeEntity> show contactdelegates [shownames] [csv]
gam create|add course [id|alias <CourseAlias>] <CourseAttribute>* gam create|add course [id|alias <CourseAlias>] <CourseAttribute>*
[copyfrom <CourseID> [copyfrom <CourseID>
[announcementstates <CourseAnnouncementStateList>] [announcementstates <CourseAnnouncementStateList>]
[individualstudentannouncements copy|delete|maptoall]
[materialstates <CourseMaterialStateList>] [materialstates <CourseMaterialStateList>]
[individualstudentmaterials copy|delete|maptoall]
[workstates <CourseWorkStateList>] [workstates <CourseWorkStateList>]
[individualstudentassignments copy|delete|maptoall] [individualstudentassignments copy|delete|maptoall]
[removeduedate [<Boolean>]] [removeduedate [<Boolean>]]
[mapsharemodestudentcopy edit|none|view] [mapsharemodestudentcopy edit|none|view]
[copymaterialsfiles [<Boolean>]] [copymaterialsfiles [<Boolean>]]
[copytopics [<Boolean>]] [copytopics [<Boolean>]]
[markdraftaspublished [<Boolean>]]
[markpublishedasdraft [<Boolean>]] [markpublishedasdraft [<Boolean>]]
[members none|all|students|teachers]] [members none|all|students|teachers]]
[logdrivefileids [<Boolean>]] [logdrivefileids [<Boolean>]]
gam update course <CourseID> <CourseAttribute>+ gam update course <CourseID> <CourseAttribute>+
[copyfrom <CourseID> [copyfrom <CourseID>
[announcementstates <CourseAnnouncementStateList>] [announcementstates <CourseAnnouncementStateList>]
[individualstudentannouncements copy|delete|maptoall]
[materialstates <CourseMaterialStateList>] [materialstates <CourseMaterialStateList>]
[individualstudentmaterials copy|delete|maptoall]
[workstates <CourseWorkStateList>] [workstates <CourseWorkStateList>]
[individualstudentassignments copy|delete|maptoall] [individualstudentassignments copy|delete|maptoall]
[removeduedate [<Boolean>]] [removeduedate [<Boolean>]]
[mapsharemodestudentcopy edit|none|view] [mapsharemodestudentcopy edit|none|view]
[copymaterialsfiles [<Boolean>]] [copymaterialsfiles [<Boolean>]]
[copytopics [<Boolean>]] [copytopics [<Boolean>]]
[markdraftaspublished [<Boolean>]]
[markpublishedasdraft [<Boolean>]] [markpublishedasdraft [<Boolean>]]
[members none|all|students|teachers]] [members none|all|students|teachers]]
[logdrivefileids [<Boolean>]] [logdrivefileids [<Boolean>]]
gam delete course <CourseID> [archive|archived]
gam update courses <CourseEntity> <CourseAttribute>+ gam update courses <CourseEntity> <CourseAttribute>+
[copyfrom <CourseID> [copyfrom <CourseID>
[announcementstates <CourseAnnouncementStateList>] [announcementstates <CourseAnnouncementStateList>]
[individualstudentannouncements copy|delete|maptoall]
[materialstates <CourseMaterialStateList>] [materialstates <CourseMaterialStateList>]
[individualstudentmaterials copy|delete|maptoall]
[workstates <CourseWorkStateList>] [workstates <CourseWorkStateList>]
[individualstudentassignments copy|delete|maptoall] [individualstudentassignments copy|delete|maptoall]
[removeduedate [<Boolean>]] [removeduedate [<Boolean>]]
[mapsharemodestudentcopy edit|none|view] [mapsharemodestudentcopy edit|none|view]
[copymaterialsfiles [<Boolean>]] [copymaterialsfiles [<Boolean>]]
[copytopics [<Boolean>]] [copytopics [<Boolean>]]
[markdraftaspublished [<Boolean>]]
[markpublishedasdraft [<Boolean>]] [markpublishedasdraft [<Boolean>]]
[members none|all|students|teachers]] [members none|all|students|teachers]]
[logdrivefileids [<Boolean>]] [logdrivefileids [<Boolean>]]
gam delete course <CourseID> [archive|archived]
gam delete courses <CourseEntity> [archive|archived] gam delete courses <CourseEntity> [archive|archived]
gam course <CourseID> create|add alias <CourseAlias> gam course <CourseID> create|add alias <CourseAlias>
@@ -3037,6 +3048,7 @@ gam print course-participants [todrive <ToDriveAttribute>*]
creationtime| creationtime|
creator|creatoruserid| creator|creatoruserid|
id| id|
individualstudentsoptions|
materials| materials|
scheduledtime| scheduledtime|
state| state|
@@ -3057,6 +3069,7 @@ gam print course-participants [todrive <ToDriveAttribute>*]
creator|creatoruserid| creator|creatoruserid|
description| description|
id| id|
individualstudentsoptions|
materials| materials|
scheduledtime| scheduledtime|
state| state|
@@ -3099,6 +3112,7 @@ gam print course-participants [todrive <ToDriveAttribute>*]
duedate| duedate|
duetime| duetime|
id| id|
individualstudentsoptions|
materials| materials|
maxpoints| maxpoints|
scheduledtime| scheduledtime|
@@ -7014,7 +7028,7 @@ gam <UserTypeEntity> print filecounts [todrive <ToDriveAttribute>*]
[filenamematchpattern <RegularExpression>] [filenamematchpattern <RegularExpression>]
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>] <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
[excludetrashed] [excludetrashed]
[showsize] [showmimetypesize] [showsize] [showmimetypesize] (addcsvdata <FieldName> <String>)*
[summary none|only|plus] [summaryuser <String>] [summary none|only|plus] [summaryuser <String>]
gam <UserTypeEntity> show filecounts gam <UserTypeEntity> show filecounts
[((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>) [((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>)

View File

@@ -2,6 +2,20 @@
Merged GAM-Team version Merged GAM-Team version
6.80.02
Added option `addcsvdata <FieldName> <String>` to `gam <UserTypeEntity> print filecounts` that adds
additional columns of data to the CSV file output.
Added options `individualstudentannouncements copy|delete|maptoall` and `individualstudentmaterials copy|delete|maptoall`
to `gam create|update course ... copyfrom` that controls how individual student announcements and materials in the `copyfrom` course are processed.
* `individualstudentannouncements copy` - Copy individual student announcements; this is the default. You will get an error if a student is not a member of the course
* `individualstudentannouncements delete` - Delete individual student announcements
* `individualstudentannouncements maptoall` - Map individual student announcements to all student announcements
* `individualstudentmaterials copy` - Copy individual student materials; this is the default. You will get an error if a student is not a member of the course
* `individualstudentmaterials delete` - Delete individual student materials
* `individualstudentmaterials maptoall` - Map individual student materials to all student materials
6.80.01 6.80.01
Added options `showstudentsaslist [<Boolean>]` and `delimiter <Character>` to `gam print course-work`. Added options `showstudentsaslist [<Boolean>]` and `delimiter <Character>` to `gam print course-work`.
@@ -16,7 +30,7 @@ have been entered in the Gmail user interface. Invalid dates are represented as
6.80.00 6.80.00
Fixed bug in `gam <UserTypeEntity> print users ... license ... formatjson` that caused a trap Fixed bug in `gam <UserTypeEntity> print users ... license ... formatjson` that caused a trap.
Upgraded to Python 3.12.5 where possible. Upgraded to Python 3.12.5 where possible.
@@ -220,7 +234,7 @@ Thanks to Jay, added option `nokey` to `gam create project` that creates a proje
Added option `individualstudentassignments copy|delete|maptoall` to `gam create|update course ... copyfrom` Added option `individualstudentassignments copy|delete|maptoall` to `gam create|update course ... copyfrom`
that controls how individual student assignments in the `copyfrom` course are processed. that controls how individual student assignments in the `copyfrom` course are processed.
* `individualstudentassignments copy` - Copy individual student assignments; this is the default. You will get an error if the student is not a member of the course. * `individualstudentassignments copy` - Copy individual student assignments; this is the default. You will get an error if a student is not a member of the course
* `individualstudentassignments delete` - Delete individual student assignments * `individualstudentassignments delete` - Delete individual student assignments
* `individualstudentassignments maptoall` - Map individual student assignments to all student assignments * `individualstudentassignments maptoall` - Map individual student assignments to all student assignments
@@ -18233,4 +18247,3 @@ This isn't elegant but it's a start; you can say:
with open(GAM_STDOUT, 'rU') as f: with open(GAM_STDOUT, 'rU') as f:
for line in f: for line in f:
sys.stdout.write(line) sys.stdout.write(line)

View File

@@ -45376,6 +45376,8 @@ class CourseAttributes():
self.courseMaterials = [] self.courseMaterials = []
self.workStates = [] self.workStates = []
self.courseWorks = [] self.courseWorks = []
self.individualStudentAnnouncements = 'copy'
self.individualStudentMaterials = 'copy'
self.individualStudentAssignments = 'copy' self.individualStudentAssignments = 'copy'
self.copyTopics = False self.copyTopics = False
self.topicsById = {} self.topicsById = {}
@@ -45452,7 +45454,7 @@ class CourseAttributes():
'view': 'VIEW' 'view': 'VIEW'
} }
COURSE_WORK_INDIVIDUAL_STUDENT_ASSIGNMENTS_OPTIONS = {'copy', 'delete', 'maptoall'} COURSE_INDIVIDUAL_STUDENT_OPTIONS = {'copy', 'delete', 'maptoall'}
def GetAttributes(self): def GetAttributes(self):
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
@@ -45483,8 +45485,12 @@ class CourseAttributes():
_getCourseStates(Cmd.OB_COURSE_WORK_STATE_LIST, self.workStates) _getCourseStates(Cmd.OB_COURSE_WORK_STATE_LIST, self.workStates)
elif myarg in {'materialstate', 'materialstates', 'coursematerialstate', 'coursematerialstates'}: elif myarg in {'materialstate', 'materialstates', 'coursematerialstate', 'coursematerialstates'}:
_getCourseStates(Cmd.OB_COURSE_MATERIAL_STATE_LIST, self.materialStates) _getCourseStates(Cmd.OB_COURSE_MATERIAL_STATE_LIST, self.materialStates)
elif myarg == 'individualstudentannouncements':
self.individualStudentAnnouncements = getChoice(self.COURSE_INDIVIDUAL_STUDENT_OPTIONS)
elif myarg == 'individualstudentmaterials':
self.individualStudentMaterials = getChoice(self.COURSE_INDIVIDUAL_STUDENT_OPTIONS)
elif myarg == 'individualstudentassignments': elif myarg == 'individualstudentassignments':
self.individualStudentAssignments = getChoice(self.COURSE_WORK_INDIVIDUAL_STUDENT_ASSIGNMENTS_OPTIONS) self.individualStudentAssignments = getChoice(self.COURSE_INDIVIDUAL_STUDENT_OPTIONS)
elif myarg == 'members': elif myarg == 'members':
self.members = getChoice(COURSE_MEMBER_ARGUMENTS) self.members = getChoice(COURSE_MEMBER_ARGUMENTS)
elif myarg == 'markdraftaspublished': elif myarg == 'markdraftaspublished':
@@ -45671,6 +45677,24 @@ class CourseAttributes():
pass pass
return False return False
def checkItemCopyable(self, state, newCourseId, entityType, entityId, body, individualStudentOption, clarg, j, jcount):
if state == 'DELETED':
entityModifierItemValueListActionNotPerformedWarning([Ent.COURSE, newCourseId, entityType, entityId], Act.MODIFIER_FROM,
[Ent.COURSE, self.courseId], Msg.DELETED, j, jcount)
return False
if body['assigneeMode'] == 'INDIVIDUAL_STUDENTS':
if individualStudentOption == 'delete':
entityModifierItemValueListActionNotPerformedWarning([Ent.COURSE, newCourseId, entityType, entityId], Act.MODIFIER_FROM,
[Ent.COURSE, self.courseId], f'{clarg} delete', j, jcount)
return False
if individualStudentOption == 'maptoall':
body['assigneeMode'] = 'ALL_STUDENTS'
body.pop('individualStudentsOptions', None)
else: # individualStudentOption == 'copy':
if 'individualStudentsOptions' not in body:
body['assigneeMode'] = 'ALL_STUDENTS'
return True
def CopyAttributes(self, newCourse, i=0, count=0): def CopyAttributes(self, newCourse, i=0, count=0):
newCourseId = newCourse['id'] newCourseId = newCourse['id']
ownerId = newCourse['ownerId'] ownerId = newCourse['ownerId']
@@ -45736,9 +45760,8 @@ class CourseAttributes():
j += 1 j += 1
body = courseAnnouncement.copy() body = courseAnnouncement.copy()
courseAnnouncementId = body.pop('id') courseAnnouncementId = body.pop('id')
if courseAnnouncement['state'] == 'DELETED': if not self.checkItemCopyable(courseAnnouncement['state'], newCourseId, Ent.COURSE_ANNOUNCEMENT_ID, courseAnnouncementId,
entityModifierItemValueListActionNotPerformedWarning([Ent.COURSE, newCourseId, Ent.COURSE_ANNOUNCEMENT_ID, courseAnnouncementId], Act.MODIFIER_FROM, body, self.individualStudentAnnouncements, 'individualstudentannouncements', j, jcount):
[Ent.COURSE, self.courseId], Msg.DELETED, j, jcount)
continue continue
if self.copyMaterialsFiles: if self.copyMaterialsFiles:
self.CopyMaterials(tdrive, newCourseId, body, Ent.COURSE_ANNOUNCEMENT_ID, courseAnnouncementId, teacherFolderId) self.CopyMaterials(tdrive, newCourseId, body, Ent.COURSE_ANNOUNCEMENT_ID, courseAnnouncementId, teacherFolderId)
@@ -45764,9 +45787,8 @@ class CourseAttributes():
j += 1 j += 1
body = courseMaterial.copy() body = courseMaterial.copy()
courseMaterialId = body.pop('id') courseMaterialId = body.pop('id')
if courseMaterial['state'] == 'DELETED': if not self.checkItemCopyable(courseMaterial['state'], newCourseId, Ent.COURSE_MATERIAL_ID, courseMaterialId,
entityModifierItemValueListActionNotPerformedWarning([Ent.COURSE, newCourseId, Ent.COURSE_MATERIAL_ID, courseMaterialId], Act.MODIFIER_FROM, body, self.individualStudentMaterials, 'individualstudentmaterials', j, jcount):
[Ent.COURSE, self.courseId], Msg.DELETED, j, jcount)
continue continue
if self.copyMaterialsFiles: if self.copyMaterialsFiles:
self.CopyMaterials(tdrive, newCourseId, body, Ent.COURSE_MATERIAL_ID, courseMaterialId, teacherFolderId) self.CopyMaterials(tdrive, newCourseId, body, Ent.COURSE_MATERIAL_ID, courseMaterialId, teacherFolderId)
@@ -45800,18 +45822,9 @@ class CourseAttributes():
j += 1 j += 1
body = courseWork.copy() body = courseWork.copy()
courseWorkId = body.pop('id') courseWorkId = body.pop('id')
if courseWork['state'] == 'DELETED': if not self.checkItemCopyable(courseWork['state'], newCourseId, Ent.COURSE_WORK_ID, courseWorkId,
entityModifierItemValueListActionNotPerformedWarning([Ent.COURSE, newCourseId, Ent.COURSE_WORK, f'{body.get("title", courseWorkId)}'], Act.MODIFIER_FROM, body, self.individualStudentAssignments, 'individualstudentassignments', j, jcount):
[Ent.COURSE, self.courseId], Msg.DELETED, j, jcount)
continue continue
if body['assigneeMode'] == 'INDIVIDUAL_STUDENTS':
if self.individualStudentAssignments == 'delete':
entityModifierItemValueListActionNotPerformedWarning([Ent.COURSE, newCourseId, Ent.COURSE_WORK, f'{body.get("title", courseWorkId)}'], Act.MODIFIER_FROM,
[Ent.COURSE, self.courseId], 'individualStudentAssignments delete', j, jcount)
continue
if self.individualStudentAssignments == 'maptoall':
body['assigneeMode'] = 'ALL_STUDENTS'
body.pop('individualStudentsOptions', None)
if self.copyMaterialsFiles: if self.copyMaterialsFiles:
self.CopyMaterials(tdrive, newCourseId, body, Ent.COURSE_WORK_ID, courseWorkId, teacherFolderId) self.CopyMaterials(tdrive, newCourseId, body, Ent.COURSE_WORK_ID, courseWorkId, teacherFolderId)
topicId = body.pop('topicId', None) topicId = body.pop('topicId', None)
@@ -45859,8 +45872,11 @@ class CourseAttributes():
# gam create course [id|alias <CourseAlias>] <CourseAttribute>* # gam create course [id|alias <CourseAlias>] <CourseAttribute>*
# [copyfrom <CourseID> # [copyfrom <CourseID>
# [announcementstates <CourseAnnouncementStateList>] # [announcementstates <CourseAnnouncementStateList>]
# [individualstudentannouncements copy|delete|maptoall]
# [materialstates <CourseMaterialStateList>] # [materialstates <CourseMaterialStateList>]
# [individualstudentmaterials copy|delete|maptoall]
# [workstates <CourseWorkStateList>] # [workstates <CourseWorkStateList>]
# [individualstudentassignments copy|delete|maptoall]
# [removeduedate [<Boolean>]] # [removeduedate [<Boolean>]]
# [mapsharemodestudentcopy edit|none|view] # [mapsharemodestudentcopy edit|none|view]
# [copymaterialsfiles [<Boolean>]] # [copymaterialsfiles [<Boolean>]]
@@ -45962,8 +45978,11 @@ def _doUpdateCourses(entityList):
# gam update courses <CourseEntity> <CourseAttribute>+ # gam update courses <CourseEntity> <CourseAttribute>+
# [copyfrom <CourseID> # [copyfrom <CourseID>
# [announcementstates <CourseAnnouncementStateList>] # [announcementstates <CourseAnnouncementStateList>]
# [individualstudentannouncements copy|delete|maptoall]
# [materialstates <CourseMaterialStateList>] # [materialstates <CourseMaterialStateList>]
# [individualstudentmaterials copy|delete|maptoall]
# [workstates <CourseWorkStateList>] # [workstates <CourseWorkStateList>]
# [individualstudentassignments copy|delete|maptoall]
# [removeduedate [<Boolean>]] # [removeduedate [<Boolean>]]
# [mapsharemodestudentcopy edit|none|view] # [mapsharemodestudentcopy edit|none|view]
# [copymaterialsfiles [<Boolean>]] # [copymaterialsfiles [<Boolean>]]
@@ -45977,8 +45996,11 @@ def doUpdateCourses():
# gam update course <CourseID> <CourseAttribute>+ # gam update course <CourseID> <CourseAttribute>+
# [copyfrom <CourseID> # [copyfrom <CourseID>
# [announcementstates <CourseAnnouncementStateList>] # [announcementstates <CourseAnnouncementStateList>]
# [individualstudentannouncements copy|delete|maptoall]
# [materialstates <CourseMaterialStateList>] # [materialstates <CourseMaterialStateList>]
# [individualstudentmaterials copy|delete|maptoall]
# [workstates <CourseWorkStateList>] # [workstates <CourseWorkStateList>]
# [individualstudentassignments copy|delete|maptoall]
# [removeduedate [<Boolean>]] # [removeduedate [<Boolean>]]
# [mapsharemodestudentcopy edit|none|view] # [mapsharemodestudentcopy edit|none|view]
# [copymaterialsfiles [<Boolean>]] # [copymaterialsfiles [<Boolean>]]
@@ -46639,6 +46661,7 @@ COURSE_ANNOUNCEMENTS_FIELDS_CHOICE_MAP = {
'creator': 'creatorUserId', 'creator': 'creatorUserId',
'creatoruserid': 'creatorUserId', 'creatoruserid': 'creatorUserId',
'id': 'id', 'id': 'id',
'individualstudentsoptions': 'individualStudentsOptions',
'materials': 'materials', 'materials': 'materials',
'scheduledtime': 'scheduledTime', 'scheduledtime': 'scheduledTime',
'state': 'state', 'state': 'state',
@@ -46868,6 +46891,7 @@ COURSE_MATERIAL_FIELDS_CHOICE_MAP = {
'creatoruserid': 'creatorUserId', 'creatoruserid': 'creatorUserId',
'description': 'description', 'description': 'description',
'id': 'id', 'id': 'id',
'individualstudentsoptions': 'individualStudentsOptions',
'materialid': 'id', 'materialid': 'id',
'materials': 'materials', 'materials': 'materials',
'scheduledtime': 'scheduledTime', 'scheduledtime': 'scheduledTime',
@@ -46896,6 +46920,7 @@ COURSE_WORK_FIELDS_CHOICE_MAP = {
'duedate': 'dueDate', 'duedate': 'dueDate',
'duetime': 'dueTime', 'duetime': 'dueTime',
'id': 'id', 'id': 'id',
'individualstudentsoptions': 'individualStudentsOptions',
'materials': 'materials', 'materials': 'materials',
'maxpoints': 'maxPoints', 'maxpoints': 'maxPoints',
'scheduledtime': 'scheduledTime', 'scheduledtime': 'scheduledTime',
@@ -55488,8 +55513,9 @@ def printFileParentTree(users):
# [sizefield quotabytesused|size] [minimumfilesize <Integer>] [maximumfilesize <Integer>] # [sizefield quotabytesused|size] [minimumfilesize <Integer>] [maximumfilesize <Integer>]
# [filenamematchpattern <RegularExpression>] # [filenamematchpattern <RegularExpression>]
# <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>] # <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
# [excludetrashed] # [excludetrashed] (addcsvdata <FieldName> <String>)*
# [summary none|only|plus] [summaryuser <String>] [showsize] # [showsize] [showmimetypesize]
# [summary none|only|plus] [summaryuser <String>]
# gam <UserTypeEntity> show filecounts # gam <UserTypeEntity> show filecounts
# [((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>) (querytime<String> <Time>)*] # [((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>) (querytime<String> <Time>)*]
# [corpora <CorporaAttribute>] # [corpora <CorporaAttribute>]
@@ -55500,7 +55526,8 @@ def printFileParentTree(users):
# [filenamematchpattern <RegularExpression>] # [filenamematchpattern <RegularExpression>]
# <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>] # <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
# [excludetrashed] # [excludetrashed]
# [summary none|only|plus] [summaryuser <String>] [showsize] # [showsize] [showmimetypesize]
# [summary none|only|plus] [summaryuser <String>]
def printShowFileCounts(users): def printShowFileCounts(users):
def _setSelectionFields(): def _setSelectionFields():
if DLP.showOwnedBy is not None: if DLP.showOwnedBy is not None:
@@ -55554,6 +55581,8 @@ def printShowFileCounts(users):
row = {'User': user, 'Total': countTotal} row = {'User': user, 'Total': countTotal}
if showSize: if showSize:
row['Size'] = sizeTotal row['Size'] = sizeTotal
if addCSVData:
row.update(addCSVData)
for mimeType, mtinfo in sorted(iter(mimeTypeInfo.items())): for mimeType, mtinfo in sorted(iter(mimeTypeInfo.items())):
row[f'{mimeType}'] = mtinfo['count'] row[f'{mimeType}'] = mtinfo['count']
if showMimeTypeSize: if showMimeTypeSize:
@@ -55572,6 +55601,7 @@ def printShowFileCounts(users):
summaryUser = FILECOUNT_SUMMARY_USER summaryUser = FILECOUNT_SUMMARY_USER
summaryMimeTypeInfo = {} summaryMimeTypeInfo = {}
fileIdEntity = {} fileIdEntity = {}
addCSVData = {}
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if csvPF and myarg == 'todrive': if csvPF and myarg == 'todrive':
@@ -55592,6 +55622,9 @@ def printShowFileCounts(users):
summary = getChoice(FILECOUNT_SUMMARY_CHOICE_MAP, mapChoice=True) summary = getChoice(FILECOUNT_SUMMARY_CHOICE_MAP, mapChoice=True)
elif myarg == 'summaryuser': elif myarg == 'summaryuser':
summaryUser = getString(Cmd.OB_STRING) summaryUser = getString(Cmd.OB_STRING)
elif csvPF and myarg == 'addcsvdata':
k = getString(Cmd.OB_STRING)
addCSVData[k] = getString(Cmd.OB_STRING, minLen=0)
else: else:
unknownArgumentExit() unknownArgumentExit()
if not fileIdEntity: if not fileIdEntity:
@@ -55612,6 +55645,8 @@ def printShowFileCounts(users):
sortTitles = ['User', 'id', 'name', 'Total', 'Item cap'] if fileIdEntity.get('shareddrive') else ['User', 'Total'] sortTitles = ['User', 'id', 'name', 'Total', 'Item cap'] if fileIdEntity.get('shareddrive') else ['User', 'Total']
if showSize: if showSize:
sortTitles.insert(sortTitles.index('Total')+1, 'Size') sortTitles.insert(sortTitles.index('Total')+1, 'Size')
if addCSVData:
sortTitles.extend(sorted(addCSVData.keys()))
csvPF.SetTitles(sortTitles) csvPF.SetTitles(sortTitles)
csvPF.SetSortAllTitles() csvPF.SetSortAllTitles()
pagesFields = getItemFieldsFromFieldsList('files', fieldsList) pagesFields = getItemFieldsFromFieldsList('files', fieldsList)
@@ -75740,3 +75775,4 @@ def ProcessGAMCommand(args, processGamCfg=True, inLoop=False, closeSTD=True):
# Process GAM command # Process GAM command
def CallGAMCommand(args, processGamCfg=True, inLoop=False, closeSTD=False): def CallGAMCommand(args, processGamCfg=True, inLoop=False, closeSTD=False):
return ProcessGAMCommand(args, processGamCfg=processGamCfg, inLoop=inLoop, closeSTD=closeSTD) return ProcessGAMCommand(args, processGamCfg=processGamCfg, inLoop=inLoop, closeSTD=closeSTD)
o