mirror of
https://github.com/GAM-team/GAM.git
synced 2026-07-03 20:31:35 +00:00
Compare commits
4 Commits
v7.05.14
...
20250328.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10a91091f2 | ||
|
|
16cef20094 | ||
|
|
e588c8851a | ||
|
|
d14cd1ad56 |
@@ -102,7 +102,7 @@ If an item contains spaces, it should be surrounded by ".
|
|||||||
banana|basil|blueberry|flamingo|graphite|grape|
|
banana|basil|blueberry|flamingo|graphite|grape|
|
||||||
lavender|peacock|sage|tangerine|tomato
|
lavender|peacock|sage|tangerine|tomato
|
||||||
<FileFormat> ::=
|
<FileFormat> ::=
|
||||||
csv|doc|dot|docx|dotx|epub|html|jpeg|jpg|mht|odp|ods|odt|
|
csv|doc|dot|docx|dotx|epub|html|jpeg|jpg|json|mht|odp|ods|odt|
|
||||||
pdf|png|ppt|pot|potx|pptx|rtf|svg|tsv|txt|xls|xlt|xlsx|xltx|zip|
|
pdf|png|ppt|pot|potx|pptx|rtf|svg|tsv|txt|xls|xlt|xlsx|xltx|zip|
|
||||||
ms|microsoft|openoffice|
|
ms|microsoft|openoffice|
|
||||||
<LabelColorHex> ::=
|
<LabelColorHex> ::=
|
||||||
@@ -1276,8 +1276,8 @@ If the pattern {{Section}} appears in <FileName>, it will be replaced with the n
|
|||||||
For redirect csv, the optional arguments must appear in the order shown.
|
For redirect csv, the optional arguments must appear in the order shown.
|
||||||
<Redirect> ::=
|
<Redirect> ::=
|
||||||
redirect csv <FileName> [multiprocess] [append] [noheader] [charset <Charset>]
|
redirect csv <FileName> [multiprocess] [append] [noheader] [charset <Charset>]
|
||||||
[columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
|
[columndelimiter <Character>] [noescapechar [<Boolean>]] [quotechar <Character>]
|
||||||
[sortheaders <StringList>] [timestampcolumn <String>]
|
[sortheaders <StringList>] [timestampcolumn <String>] [transpose [<Bopolean>]]
|
||||||
[todrive <ToDriveAttribute>*] |
|
[todrive <ToDriveAttribute>*] |
|
||||||
redirect stdout <FileName> [multiprocess] [append] |
|
redirect stdout <FileName> [multiprocess] [append] |
|
||||||
redirect stdout null [multiprocess] |
|
redirect stdout null [multiprocess] |
|
||||||
|
|||||||
@@ -1,3 +1,21 @@
|
|||||||
|
7.05.16
|
||||||
|
|
||||||
|
Added option `transpose [<Boolean>]` to `redirect csv` that causes
|
||||||
|
GAM to transpose CSV output rows and columns. This will most useful
|
||||||
|
when a `countsonly` option is used in a `print` or `report` command.
|
||||||
|
|
||||||
|
7.05.15
|
||||||
|
|
||||||
|
Updated `gam <UserTypeEntity> get drivefile` and `gam <UserTypeEntity> create drivefile`
|
||||||
|
to allow downloading and uploading of Google Apps Scripts.
|
||||||
|
```
|
||||||
|
$ gam user user1@domain.com get drivefile 1ZY-YkS3E0OKipALra_XzfIh9cvxoILSbb8TRdHBFCpyB_mXI_J8FmjHv format json
|
||||||
|
User: user1@domain.com, Download 1 Drive File
|
||||||
|
User: user1@domain.com, Drive File: Test Project, Downloaded to: /Users/gamteam/GamWork/Test Project.json, Type: Google Doc
|
||||||
|
$ gam user user2@domain.com create drivefile localfile "Test Project.json" mimetype application/vnd.google-apps.script+json drivefilename "Test Project"
|
||||||
|
User: user2@domain.com, Drive File: Test Project(1Ok_svw55VTreZ5CzcViJDLfEzVRi-Un8D9eG6I5pIeVyRl2YsmNiy3C_), Created with content from: Test Project.json
|
||||||
|
```
|
||||||
|
|
||||||
7.05.14
|
7.05.14
|
||||||
|
|
||||||
Added the following License SKU:
|
Added the following License SKU:
|
||||||
|
|||||||
@@ -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.05.14'
|
__version__ = '7.05.16'
|
||||||
__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
|
||||||
@@ -262,6 +262,7 @@ MIMETYPE_GA_JAM = f'{APPLICATION_VND_GOOGLE_APPS}jam'
|
|||||||
MIMETYPE_GA_MAP = f'{APPLICATION_VND_GOOGLE_APPS}map'
|
MIMETYPE_GA_MAP = f'{APPLICATION_VND_GOOGLE_APPS}map'
|
||||||
MIMETYPE_GA_PRESENTATION = f'{APPLICATION_VND_GOOGLE_APPS}presentation'
|
MIMETYPE_GA_PRESENTATION = f'{APPLICATION_VND_GOOGLE_APPS}presentation'
|
||||||
MIMETYPE_GA_SCRIPT = f'{APPLICATION_VND_GOOGLE_APPS}script'
|
MIMETYPE_GA_SCRIPT = f'{APPLICATION_VND_GOOGLE_APPS}script'
|
||||||
|
MIMETYPE_GA_SCRIPT_JSON = f'{APPLICATION_VND_GOOGLE_APPS}script+json'
|
||||||
MIMETYPE_GA_SHORTCUT = f'{APPLICATION_VND_GOOGLE_APPS}shortcut'
|
MIMETYPE_GA_SHORTCUT = f'{APPLICATION_VND_GOOGLE_APPS}shortcut'
|
||||||
MIMETYPE_GA_3P_SHORTCUT = f'{APPLICATION_VND_GOOGLE_APPS}drive-sdk'
|
MIMETYPE_GA_3P_SHORTCUT = f'{APPLICATION_VND_GOOGLE_APPS}drive-sdk'
|
||||||
MIMETYPE_GA_SITE = f'{APPLICATION_VND_GOOGLE_APPS}site'
|
MIMETYPE_GA_SITE = f'{APPLICATION_VND_GOOGLE_APPS}site'
|
||||||
@@ -4112,8 +4113,8 @@ def SetGlobalVariables():
|
|||||||
if checkArgumentPresent(Cmd.MULTIPROCESSEXIT_CMD):
|
if checkArgumentPresent(Cmd.MULTIPROCESSEXIT_CMD):
|
||||||
_setMultiprocessExit()
|
_setMultiprocessExit()
|
||||||
# redirect csv <FileName> [multiprocess] [append] [noheader] [charset <CharSet>]
|
# redirect csv <FileName> [multiprocess] [append] [noheader] [charset <CharSet>]
|
||||||
# [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]]
|
# [columndelimiter <Character>] [noescapechar [<Boolean>]] [quotechar <Character>]]
|
||||||
# [sortheaders <StringList>] [timestampcolumn <String>]
|
# [sortheaders <StringList>] [timestampcolumn <String>] [transpose [<Boolean>]]
|
||||||
# [todrive <ToDriveAttribute>*]
|
# [todrive <ToDriveAttribute>*]
|
||||||
# redirect stdout <FileName> [multiprocess] [append]
|
# redirect stdout <FileName> [multiprocess] [append]
|
||||||
# redirect stdout null
|
# redirect stdout null
|
||||||
@@ -4138,6 +4139,8 @@ def SetGlobalVariables():
|
|||||||
GM.Globals[GM.CSV_OUTPUT_SORT_HEADERS] = GC.Values[GC.CSV_OUTPUT_SORT_HEADERS] = getString(Cmd.OB_STRING_LIST, minLen=0).replace(',', ' ').split()
|
GM.Globals[GM.CSV_OUTPUT_SORT_HEADERS] = GC.Values[GC.CSV_OUTPUT_SORT_HEADERS] = getString(Cmd.OB_STRING_LIST, minLen=0).replace(',', ' ').split()
|
||||||
if checkArgumentPresent('timestampcolumn'):
|
if checkArgumentPresent('timestampcolumn'):
|
||||||
GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN] = GC.Values[GC.CSV_OUTPUT_TIMESTAMP_COLUMN] = getString(Cmd.OB_STRING, minLen=0)
|
GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN] = GC.Values[GC.CSV_OUTPUT_TIMESTAMP_COLUMN] = getString(Cmd.OB_STRING, minLen=0)
|
||||||
|
if checkArgumentPresent('transpose'):
|
||||||
|
GM.Globals[GM.CSV_OUTPUT_TRANSPOSE] = getBoolean()
|
||||||
_setCSVFile(filename, mode, encoding, writeHeader, multi)
|
_setCSVFile(filename, mode, encoding, writeHeader, multi)
|
||||||
GM.Globals[GM.CSVFILE][GM.REDIRECT_QUEUE_CSVPF] = CSVPrintFile()
|
GM.Globals[GM.CSVFILE][GM.REDIRECT_QUEUE_CSVPF] = CSVPrintFile()
|
||||||
if checkArgumentPresent('todrive'):
|
if checkArgumentPresent('todrive'):
|
||||||
@@ -4446,7 +4449,7 @@ def handleOAuthTokenError(e, softErrors, displayError=False, i=0, count=0):
|
|||||||
if not GM.Globals[GM.CURRENT_SVCACCT_USER]:
|
if not GM.Globals[GM.CURRENT_SVCACCT_USER]:
|
||||||
ClientAPIAccessDeniedExit()
|
ClientAPIAccessDeniedExit()
|
||||||
if softErrors:
|
if softErrors:
|
||||||
entityDoesNotExistWarning(Ent.USER, GM.Globals[GM.CURRENT_SVCACCT_USER], i, count)
|
entityActionFailedWarning([Ent.USER, GM.Globals[GM.CURRENT_SVCACCT_USER], Ent.USER, None], errMsg, i, count)
|
||||||
return None
|
return None
|
||||||
systemErrorExit(SERVICE_NOT_APPLICABLE_RC, Msg.SERVICE_NOT_APPLICABLE_THIS_ADDRESS.format(GM.Globals[GM.CURRENT_SVCACCT_USER]))
|
systemErrorExit(SERVICE_NOT_APPLICABLE_RC, Msg.SERVICE_NOT_APPLICABLE_THIS_ADDRESS.format(GM.Globals[GM.CURRENT_SVCACCT_USER]))
|
||||||
if errMsg in API.OAUTH2_UNAUTHORIZED_ERRORS:
|
if errMsg in API.OAUTH2_UNAUTHORIZED_ERRORS:
|
||||||
@@ -7793,6 +7796,7 @@ class CSVPrintFile():
|
|||||||
def __init__(self, titles=None, sortTitles=None, indexedTitles=None):
|
def __init__(self, titles=None, sortTitles=None, indexedTitles=None):
|
||||||
self.rows = []
|
self.rows = []
|
||||||
self.rowCount = 0
|
self.rowCount = 0
|
||||||
|
self.outputTranspose = GM.Globals[GM.CSV_OUTPUT_TRANSPOSE]
|
||||||
self.todrive = GM.Globals[GM.CSV_TODRIVE]
|
self.todrive = GM.Globals[GM.CSV_TODRIVE]
|
||||||
self.titlesSet = set()
|
self.titlesSet = set()
|
||||||
self.titlesList = []
|
self.titlesList = []
|
||||||
@@ -8992,6 +8996,22 @@ class CSVPrintFile():
|
|||||||
self.JSONtitlesList = self.orderHeaders(self.JSONtitlesList)
|
self.JSONtitlesList = self.orderHeaders(self.JSONtitlesList)
|
||||||
titlesList = self.JSONtitlesList
|
titlesList = self.JSONtitlesList
|
||||||
normalizeSortHeaders()
|
normalizeSortHeaders()
|
||||||
|
if self.outputTranspose:
|
||||||
|
newRows = []
|
||||||
|
pivotKey = titlesList[0]
|
||||||
|
newTitlesList = [pivotKey]
|
||||||
|
newTitlesSet = set(newTitlesList)
|
||||||
|
for title in titlesList[1:]:
|
||||||
|
newRow = {pivotKey: title}
|
||||||
|
for row in self.rows:
|
||||||
|
pivotValue = row[pivotKey]
|
||||||
|
if pivotValue not in newTitlesSet:
|
||||||
|
newTitlesSet.add(pivotValue)
|
||||||
|
newTitlesList.append(pivotValue)
|
||||||
|
newRow[pivotValue] = row.get(title)
|
||||||
|
newRows.append(newRow)
|
||||||
|
titlesList = newTitlesList
|
||||||
|
self.rows = newRows
|
||||||
if (not self.todrive) or self.todrive['localcopy']:
|
if (not self.todrive) or self.todrive['localcopy']:
|
||||||
if GM.Globals[GM.CSVFILE][GM.REDIRECT_NAME] == '-':
|
if GM.Globals[GM.CSVFILE][GM.REDIRECT_NAME] == '-':
|
||||||
if GM.Globals[GM.STDOUT][GM.REDIRECT_MULTI_FD]:
|
if GM.Globals[GM.STDOUT][GM.REDIRECT_MULTI_FD]:
|
||||||
@@ -57402,6 +57422,8 @@ def createDriveFile(users):
|
|||||||
if parameters[DFA_LOCALFILEPATH]:
|
if parameters[DFA_LOCALFILEPATH]:
|
||||||
if parameters[DFA_LOCALFILEPATH] != '-' and parameters[DFA_PRESERVE_FILE_TIMES]:
|
if parameters[DFA_LOCALFILEPATH] != '-' and parameters[DFA_PRESERVE_FILE_TIMES]:
|
||||||
setPreservedFileTimes(body, parameters, False)
|
setPreservedFileTimes(body, parameters, False)
|
||||||
|
if body.get('mimeType') == MIMETYPE_GA_SCRIPT_JSON:
|
||||||
|
parameters[DFA_LOCALMIMETYPE] = body['mimeType']
|
||||||
media_body = getMediaBody(parameters)
|
media_body = getMediaBody(parameters)
|
||||||
elif parameters[DFA_URL]:
|
elif parameters[DFA_URL]:
|
||||||
media_body = getMediaBody(parameters)
|
media_body = getMediaBody(parameters)
|
||||||
@@ -60439,6 +60461,7 @@ GOOGLEDOC_VALID_EXTENSIONS_MAP = {
|
|||||||
MIMETYPE_GA_DOCUMENT: ['.docx', '.epub', '.html', '.odt', '.pdf', '.rtf', '.txt', '.zip'],
|
MIMETYPE_GA_DOCUMENT: ['.docx', '.epub', '.html', '.odt', '.pdf', '.rtf', '.txt', '.zip'],
|
||||||
MIMETYPE_GA_JAM: ['.pdf'],
|
MIMETYPE_GA_JAM: ['.pdf'],
|
||||||
MIMETYPE_GA_PRESENTATION: ['.pdf', '.pptx', '.odp', '.txt'],
|
MIMETYPE_GA_PRESENTATION: ['.pdf', '.pptx', '.odp', '.txt'],
|
||||||
|
MIMETYPE_GA_SCRIPT: ['.json'],
|
||||||
MIMETYPE_GA_SPREADSHEET: ['.csv', '.ods', '.pdf', '.tsv', '.xlsx', '.zip'],
|
MIMETYPE_GA_SPREADSHEET: ['.csv', '.ods', '.pdf', '.tsv', '.xlsx', '.zip'],
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60474,6 +60497,7 @@ DOCUMENT_FORMATS_MAP = {
|
|||||||
'html': [{'mime': 'text/html', 'ext': '.html'}],
|
'html': [{'mime': 'text/html', 'ext': '.html'}],
|
||||||
'jpeg': [{'mime': 'image/jpeg', 'ext': '.jpeg'}],
|
'jpeg': [{'mime': 'image/jpeg', 'ext': '.jpeg'}],
|
||||||
'jpg': [{'mime': 'image/jpeg', 'ext': '.jpg'}],
|
'jpg': [{'mime': 'image/jpeg', 'ext': '.jpg'}],
|
||||||
|
'json': [{'mime': MIMETYPE_GA_SCRIPT_JSON, 'ext': '.json'}],
|
||||||
'mht': [{'mime': 'message/rfc822', 'ext': 'mht'}],
|
'mht': [{'mime': 'message/rfc822', 'ext': 'mht'}],
|
||||||
'odp': [{'mime': 'application/vnd.oasis.opendocument.presentation', 'ext': '.odp'}],
|
'odp': [{'mime': 'application/vnd.oasis.opendocument.presentation', 'ext': '.odp'}],
|
||||||
'ods': [{'mime': 'application/x-vnd.oasis.opendocument.spreadsheet', 'ext': '.ods'},
|
'ods': [{'mime': 'application/x-vnd.oasis.opendocument.spreadsheet', 'ext': '.ods'},
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ CSV_OUTPUT_ROW_FILTER_MODE = 'corm'
|
|||||||
CSV_OUTPUT_ROW_LIMIT = 'corl'
|
CSV_OUTPUT_ROW_LIMIT = 'corl'
|
||||||
# Add timestamp column to CSV output file
|
# Add timestamp column to CSV output file
|
||||||
CSV_OUTPUT_TIMESTAMP_COLUMN = 'cotc'
|
CSV_OUTPUT_TIMESTAMP_COLUMN = 'cotc'
|
||||||
|
# Transpose output rows/columns
|
||||||
|
CSV_OUTPUT_TRANSPOSE = 'cotr'
|
||||||
# Output sort headers
|
# Output sort headers
|
||||||
CSV_OUTPUT_SORT_HEADERS = 'cosh'
|
CSV_OUTPUT_SORT_HEADERS = 'cosh'
|
||||||
# CSV todrive options
|
# CSV todrive options
|
||||||
@@ -250,6 +252,7 @@ Globals = {
|
|||||||
CSV_OUTPUT_ROW_LIMIT: 0,
|
CSV_OUTPUT_ROW_LIMIT: 0,
|
||||||
CSV_OUTPUT_SORT_HEADERS: [],
|
CSV_OUTPUT_SORT_HEADERS: [],
|
||||||
CSV_OUTPUT_TIMESTAMP_COLUMN: None,
|
CSV_OUTPUT_TIMESTAMP_COLUMN: None,
|
||||||
|
CSV_OUTPUT_TRANSPOSE: False,
|
||||||
CSV_TODRIVE: {},
|
CSV_TODRIVE: {},
|
||||||
CURRENT_API_SERVICES: {},
|
CURRENT_API_SERVICES: {},
|
||||||
CURRENT_CLIENT_API: None,
|
CURRENT_CLIENT_API: None,
|
||||||
|
|||||||
Reference in New Issue
Block a user