Refactor into Python package format (#1165)

* Refactor into a python module format

-Updates import statements to be absolute vs implicitly relative
-Uses import syntax that minimizes the need to update references in code
and/or reformat affected lines (e.g. `import gapi.directory` becomes `from gam.gapi import directory as
gapi_directory`)
-Adds a `__main__.py` such that the module can be executed on its own
using standard `python3 -m gam` syntax
-Replaces __main__ import hack with module import
-Updates the GAM path to be the module's parent dir

* Add gam.py to /src for backwards compatibility

A stub that calls gam.__main__.main() to be used by users who are not
with the syntax of calling a module implementation. It should also
provide immediate backwards-compatibility with existing scripts with
references to this file.

* Move build tools back to the main dir and out of the package

* Fix pylint errors

* Update build spec to use new package format

Incorporates @jay0lee's patch from
https://github.com/jay0lee/GAM/pull/1165#issuecomment-618430828
This commit is contained in:
ejochman
2020-04-23 11:06:30 -07:00
committed by GitHub
parent 5f6306911f
commit e1660aa909
34 changed files with 11871 additions and 11850 deletions

1
src/.gitignore vendored
View File

@ -64,7 +64,6 @@ nobrowser.txt
nocache.txt nocache.txt
noverifyssl.txt noverifyssl.txt
gamcache/ gamcache/
gam/
gam-64/ gam-64/
*.zip *.zip
*.msi *.msi

11604
src/gam.py

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@ extra_files += [(os.path.join(proot, 'cacerts.txt'), 'httplib2')]
extra_files += copy_metadata('google-api-python-client') extra_files += copy_metadata('google-api-python-client')
a = Analysis(['gam.py'], a = Analysis(['gam/__main__.py'],
hiddenimports=[], hiddenimports=[],
hookspath=None, hookspath=None,
excludes=['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter'], excludes=['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter'],

11576
src/gam/__init__.py Executable file

File diff suppressed because it is too large Load Diff

47
src/gam/__main__.py Normal file
View File

@ -0,0 +1,47 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# GAM
#
# Copyright 2019, LLC All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""GAM is a command line tool which allows Administrators to control their G Suite domain and accounts.
With GAM you can programmatically create users, turn on/off services for users like POP and Forwarding and much more.
For more information, see https://git.io/gam
"""
import sys
from multiprocessing import freeze_support
from multiprocessing import set_start_method
from gam import controlflow
import gam
def main(argv):
freeze_support()
if sys.platform == 'darwin':
# https://bugs.python.org/issue33725 in Python 3.8.0 seems
# to break parallel operations with errors about extra -b
# command line arguments
set_start_method('fork')
if sys.version_info[0] < 3 or sys.version_info[1] < 6:
controlflow.system_error_exit(5,
f'GAM requires Python 3.6 or newer. You are running %s.%s.%s. Please upgrade your Python version or use one of the binary GAM downloads.' % sys.version_info[
:3])
sys.exit(gam.ProcessGAMCommand(sys.argv))
# Run from command line
if __name__ == "__main__":
main(sys.argv)

View File

@ -1,10 +1,10 @@
"""Authentication/Credentials general purpose and convenience methods.""" """Authentication/Credentials general purpose and convenience methods."""
import transport from gam.auth import oauth
from var import _FN_OAUTH2_TXT from gam.var import _FN_OAUTH2_TXT
from var import GC_OAUTH2_TXT from gam.var import GC_OAUTH2_TXT
from var import GC_Values from gam.var import GC_Values
from . import oauth
# TODO: Move logic that determines file name into this module. We should be able # TODO: Move logic that determines file name into this module. We should be able
# to discover the file location without accessing a private member or waiting # to discover the file location without accessing a private member or waiting
# for a global initialization. # for a global initialization.

View File

@ -12,12 +12,11 @@ import google_auth_oauthlib.flow
import google.oauth2.credentials import google.oauth2.credentials
import google.oauth2.id_token import google.oauth2.id_token
import fileutils from gam import fileutils
import transport from gam import transport
from var import GAM_INFO from gam.var import GM_Globals
from var import GM_Globals from gam.var import GM_WINDOWS
from var import GM_WINDOWS from gam import utils
import utils
MESSAGE_CONSOLE_AUTHORIZATION_PROMPT = ('\nGo to the following link in your ' MESSAGE_CONSOLE_AUTHORIZATION_PROMPT = ('\nGo to the following link in your '
'browser:\n\n\t{url}\n') 'browser:\n\n\t{url}\n')

View File

@ -10,7 +10,7 @@ from unittest.mock import patch
import google.oauth2.credentials import google.oauth2.credentials
from auth import oauth from gam.auth import oauth
class CredentialsTest(unittest.TestCase): class CredentialsTest(unittest.TestCase):

View File

@ -3,9 +3,9 @@ import random
import sys import sys
import time import time
import display # TODO: Change to relative import when gam is setup as a package from gam import display
from var import MESSAGE_HEADER_NOT_FOUND_IN_CSV_HEADERS from gam.var import MESSAGE_HEADER_NOT_FOUND_IN_CSV_HEADERS
from var import MESSAGE_INVALID_JSON from gam.var import MESSAGE_INVALID_JSON
def system_error_exit(return_code, message): def system_error_exit(return_code, message):
@ -21,38 +21,35 @@ def system_error_exit(return_code, message):
def invalid_argument_exit(argument, command): def invalid_argument_exit(argument, command):
'''Indicate that the argument is not valid for the command. """Indicate that the argument is not valid for the command.
Args: Args:
argument: the invalid argument argument: the invalid argument
command: the base GAM command command: the base GAM command
''' """
system_error_exit( system_error_exit(2, f'{argument} is not a valid argument for "{command}"')
2,
f'{argument} is not a valid argument for "{command}"')
def missing_argument_exit(argument, command): def missing_argument_exit(argument, command):
'''Indicate that the argument is missing for the command. """Indicate that the argument is missing for the command.
Args: Args:
argument: the missingagrument argument: the missingagrument
command: the base GAM command command: the base GAM command
''' """
system_error_exit( system_error_exit(2, f'missing argument {argument} for "{command}"')
2,
f'missing argument {argument} for "{command}"')
def expected_argument_exit(name, expected, argument): def expected_argument_exit(name, expected, argument):
'''Indicate that the argument does not have an expected value for the command. """Indicate that the argument does not have an expected value for the command.
Args: Args:
name: the field name name: the field name
expected: the expected values expected: the expected values
argument: the invalid argument argument: the invalid argument
''' """
system_error_exit( system_error_exit(2, f'{name} must be one of {expected}; got {argument}')
2,
f'{name} must be one of {expected}; got {argument}')
def csv_field_error_exit(field_name, field_names): def csv_field_error_exit(field_name, field_names):
"""Raises a system exit when a CSV field is malformed. """Raises a system exit when a CSV field is malformed.
@ -93,7 +90,7 @@ def wait_on_failure(current_attempt_num,
60) + float(random.randint(1, 1000)) / 1000 60) + float(random.randint(1, 1000)) / 1000
if current_attempt_num > error_print_threshold: if current_attempt_num > error_print_threshold:
sys.stderr.write((f'Temporary error: {error_message}, Backing off: ' sys.stderr.write((f'Temporary error: {error_message}, Backing off: '
f'{int(wait_on_fail)} seconds, Retry: ' f'{int(wait_on_fail)} seconds, Retry: '
f'{current_attempt_num}/{total_num_retries}\n')) f'{current_attempt_num}/{total_num_retries}\n'))
sys.stderr.flush() sys.stderr.flush()
time.sleep(wait_on_fail) time.sleep(wait_on_fail)

View File

@ -3,7 +3,7 @@
import unittest import unittest
from unittest.mock import patch from unittest.mock import patch
import controlflow from gam import controlflow
class ControlFlowTest(unittest.TestCase): class ControlFlowTest(unittest.TestCase):

View File

@ -10,10 +10,10 @@ import dateutil
import googleapiclient.http import googleapiclient.http
#TODO: get rid of these hacks #TODO: get rid of these hacks
import __main__ import gam
from var import * from gam.var import *
import controlflow from gam import controlflow
import gapi from gam import gapi
def current_count(i, count): def current_count(i, count):
@ -171,8 +171,8 @@ def write_csv_file(csvRows, titles, list_type, todrive):
except IOError as e: except IOError as e:
controlflow.system_error_exit(6, e) controlflow.system_error_exit(6, e)
if todrive: if todrive:
admin_email = __main__._getValueFromOAuth('email') admin_email = gam._getValueFromOAuth('email')
_, drive = __main__.buildDrive3GAPIObject(admin_email) _, drive = gam.buildDrive3GAPIObject(admin_email)
if not drive: if not drive:
print(f'''\nGAM is not authorized to create Drive files. Please run: print(f'''\nGAM is not authorized to create Drive files. Please run:
gam user {admin_email} check serviceaccount gam user {admin_email} check serviceaccount
@ -200,7 +200,7 @@ and follow recommend steps to authorize GAM for Drive access.''')
if GC_Values[GC_NO_BROWSER]: if GC_Values[GC_NO_BROWSER]:
msg_txt = f'Drive file uploaded to:\n {file_url}' msg_txt = f'Drive file uploaded to:\n {file_url}'
msg_subj = f'{GC_Values[GC_DOMAIN]} - {list_type}' msg_subj = f'{GC_Values[GC_DOMAIN]} - {list_type}'
__main__.send_email(msg_subj, msg_txt) gam.send_email(msg_subj, msg_txt)
print(msg_txt) print(msg_txt)
else: else:
webbrowser.open(file_url) webbrowser.open(file_url)

View File

@ -3,9 +3,9 @@
import unittest import unittest
from unittest.mock import patch from unittest.mock import patch
import display from gam import display
from var import ERROR_PREFIX from gam.var import ERROR_PREFIX
from var import WARNING_PREFIX from gam.var import WARNING_PREFIX
class DisplayTest(unittest.TestCase): class DisplayTest(unittest.TestCase):

View File

@ -4,11 +4,11 @@ import io
import os import os
import sys import sys
import controlflow from gam import controlflow
import display from gam import display
from var import GM_Globals from gam.var import GM_Globals
from var import GM_SYS_ENCODING from gam.var import GM_SYS_ENCODING
from var import UTF8_SIG from gam.var import UTF8_SIG
def _open_file(filename, mode, encoding=None, newline=None): def _open_file(filename, mode, encoding=None, newline=None):

View File

@ -6,7 +6,7 @@ import unittest
from unittest.mock import MagicMock from unittest.mock import MagicMock
from unittest.mock import patch from unittest.mock import patch
import fileutils from gam import fileutils
class FileutilsTest(unittest.TestCase): class FileutilsTest(unittest.TestCase):

View File

@ -6,14 +6,14 @@ import googleapiclient.errors
import google.auth.exceptions import google.auth.exceptions
import httplib2 import httplib2
import controlflow from gam import controlflow
import display from gam import display
from gapi import errors from gam.gapi import errors
import transport from gam import transport
from var import (GM_Globals, GM_CURRENT_API_SCOPES, GM_CURRENT_API_USER, from gam.var import (GM_Globals, GM_CURRENT_API_SCOPES, GM_CURRENT_API_USER,
GM_EXTRA_ARGS_DICT, GM_OAUTH2SERVICE_ACCOUNT_CLIENT_ID, GM_EXTRA_ARGS_DICT, GM_OAUTH2SERVICE_ACCOUNT_CLIENT_ID,
MAX_RESULTS_API_EXCEPTIONS, MESSAGE_API_ACCESS_CONFIG, MAX_RESULTS_API_EXCEPTIONS, MESSAGE_API_ACCESS_CONFIG,
MESSAGE_API_ACCESS_DENIED, MESSAGE_SERVICE_NOT_APPLICABLE) MESSAGE_API_ACCESS_DENIED, MESSAGE_SERVICE_NOT_APPLICABLE)
def call(service, def call(service,

View File

@ -6,8 +6,8 @@ from unittest.mock import MagicMock
from unittest.mock import patch from unittest.mock import patch
from gam import SetGlobalVariables from gam import SetGlobalVariables
import gapi import gam.gapi as gapi
from gapi import errors from gam.gapi import errors
def create_http_error(status, reason, message): def create_http_error(status, reason, message):

View File

@ -3,28 +3,28 @@ import sys
import uuid import uuid
# TODO: get rid of these hacks # TODO: get rid of these hacks
import __main__ import gam
from var import * from gam.var import *
import controlflow from gam import controlflow
import display from gam import display
import fileutils from gam import fileutils
import gapi from gam import gapi
import utils from gam import utils
def normalizeCalendarId(calname, checkPrimary=False): def normalizeCalendarId(calname, checkPrimary=False):
if checkPrimary and calname.lower() == 'primary': if checkPrimary and calname.lower() == 'primary':
return calname return calname
if not GC_Values[GC_DOMAIN]: if not GC_Values[GC_DOMAIN]:
GC_Values[GC_DOMAIN] = __main__._getValueFromOAuth('hd') GC_Values[GC_DOMAIN] = gam._getValueFromOAuth('hd')
return __main__.convertUIDtoEmailAddress(calname, return gam.convertUIDtoEmailAddress(calname,
email_types=['user', 'resource']) email_types=['user', 'resource'])
def buildCalendarGAPIObject(calname): def buildCalendarGAPIObject(calname):
calendarId = normalizeCalendarId(calname) calendarId = normalizeCalendarId(calname)
return (calendarId, __main__.buildGAPIServiceObject('calendar', return (calendarId, gam.buildGAPIServiceObject('calendar',
calendarId)) calendarId))
@ -36,9 +36,9 @@ def buildCalendarDataGAPIObject(calname):
# so we need to access them as the admin. # so we need to access them as the admin.
cal = None cal = None
if not calname.endswith('.calendar.google.com'): if not calname.endswith('.calendar.google.com'):
cal = __main__.buildGAPIServiceObject('calendar', calendarId, False) cal = gam.buildGAPIServiceObject('calendar', calendarId, False)
if cal is None: if cal is None:
_, cal = buildCalendarGAPIObject(__main__._getValueFromOAuth('email')) _, cal = buildCalendarGAPIObject(gam._getValueFromOAuth('email'))
return (calendarId, cal) return (calendarId, cal)
def printShowACLs(csvFormat): def printShowACLs(csvFormat):
@ -87,7 +87,7 @@ def _getCalendarACLScope(i, body):
body['scope']['type'] = myarg body['scope']['type'] = myarg
i += 1 i += 1
if myarg in ['user', 'group']: if myarg in ['user', 'group']:
body['scope']['value'] = __main__.normalizeEmailAddressOrUID( body['scope']['value'] = gam.normalizeEmailAddressOrUID(
sys.argv[i], noUid=True) sys.argv[i], noUid=True)
i += 1 i += 1
elif myarg == 'domain': elif myarg == 'domain':
@ -99,7 +99,7 @@ def _getCalendarACLScope(i, body):
body['scope']['value'] = GC_Values[GC_DOMAIN] body['scope']['value'] = GC_Values[GC_DOMAIN]
elif myarg != 'default': elif myarg != 'default':
body['scope']['type'] = 'user' body['scope']['type'] = 'user'
body['scope']['value'] = __main__.normalizeEmailAddressOrUID( body['scope']['value'] = gam.normalizeEmailAddressOrUID(
myarg, noUid=True) myarg, noUid=True)
return i return i
@ -130,7 +130,7 @@ def addACL(function):
while i < len(sys.argv): while i < len(sys.argv):
myarg = sys.argv[i].lower().replace('_', '') myarg = sys.argv[i].lower().replace('_', '')
if myarg == 'sendnotifications': if myarg == 'sendnotifications':
sendNotifications = __main__.getBoolean(sys.argv[i+1], myarg) sendNotifications = gam.getBoolean(sys.argv[i+1], myarg)
i += 2 i += 2
else: else:
controlflow.invalid_argument_exit( controlflow.invalid_argument_exit(
@ -237,7 +237,7 @@ def getSendUpdates(myarg, i, cal):
sendUpdates = 'all' sendUpdates = 'all'
i += 1 i += 1
elif myarg == 'sendnotifications': elif myarg == 'sendnotifications':
sendUpdates = 'all' if __main__.getBoolean(sys.argv[i+1], myarg) else 'none' sendUpdates = 'all' if gam.getBoolean(sys.argv[i+1], myarg) else 'none'
i += 2 i += 2
else: # 'sendupdates': else: # 'sendupdates':
sendUpdatesMap = {} sendUpdatesMap = {}
@ -393,18 +393,18 @@ def getEventAttributes(i, calendarId, cal, body, action):
body['guestsCanInviteOthers'] = False body['guestsCanInviteOthers'] = False
i += 1 i += 1
elif myarg == 'guestscaninviteothers': elif myarg == 'guestscaninviteothers':
body['guestsCanInviteTohters'] = __main__.getBoolean( body['guestsCanInviteTohters'] = gam.getBoolean(
sys.argv[i+1], 'guestscaninviteothers') sys.argv[i+1], 'guestscaninviteothers')
i += 2 i += 2
elif myarg == 'guestscantseeothers': elif myarg == 'guestscantseeothers':
body['guestsCanSeeOtherGuests'] = False body['guestsCanSeeOtherGuests'] = False
i += 1 i += 1
elif myarg == 'guestscanseeothers': elif myarg == 'guestscanseeothers':
body['guestsCanSeeOtherGuests'] = __main__.getBoolean( body['guestsCanSeeOtherGuests'] = gam.getBoolean(
sys.argv[i+1], 'guestscanseeothers') sys.argv[i+1], 'guestscanseeothers')
i += 2 i += 2
elif myarg == 'guestscanmodify': elif myarg == 'guestscanmodify':
body['guestsCanModify'] = __main__.getBoolean( body['guestsCanModify'] = gam.getBoolean(
sys.argv[i+1], 'guestscanmodify') sys.argv[i+1], 'guestscanmodify')
i += 2 i += 2
elif myarg == 'id': elif myarg == 'id':
@ -458,7 +458,7 @@ def getEventAttributes(i, calendarId, cal, body, action):
i += 1 i += 1
elif myarg == 'reminder': elif myarg == 'reminder':
minutes = \ minutes = \
__main__.getInteger(sys.argv[i+1], myarg, minVal=0, gam.getInteger(sys.argv[i+1], myarg, minVal=0,
maxVal=CALENDAR_REMINDER_MAX_MINUTES) maxVal=CALENDAR_REMINDER_MAX_MINUTES)
reminder = {'minutes': minutes, 'method': sys.argv[i+2]} reminder = {'minutes': minutes, 'method': sys.argv[i+2]}
body.setdefault( body.setdefault(
@ -483,7 +483,7 @@ def getEventAttributes(i, calendarId, cal, body, action):
body['extendedProperties']['shared'][sys.argv[i+1]] = sys.argv[i+2] body['extendedProperties']['shared'][sys.argv[i+1]] = sys.argv[i+2]
i += 3 i += 3
elif myarg == 'colorindex': elif myarg == 'colorindex':
body['colorId'] = __main__.getInteger( body['colorId'] = gam.getInteger(
sys.argv[i+1], myarg, CALENDAR_EVENT_MIN_COLOR_INDEX, sys.argv[i+1], myarg, CALENDAR_EVENT_MIN_COLOR_INDEX,
CALENDAR_EVENT_MAX_COLOR_INDEX) CALENDAR_EVENT_MAX_COLOR_INDEX)
i += 2 i += 2
@ -649,25 +649,25 @@ def getCalendarAttributes(i, body, function):
while i < len(sys.argv): while i < len(sys.argv):
myarg = sys.argv[i].lower().replace('_', '') myarg = sys.argv[i].lower().replace('_', '')
if myarg == 'selected': if myarg == 'selected':
body['selected'] = __main__.getBoolean(sys.argv[i+1], myarg) body['selected'] = gam.getBoolean(sys.argv[i+1], myarg)
i += 2 i += 2
elif myarg == 'hidden': elif myarg == 'hidden':
body['hidden'] = __main__.getBoolean(sys.argv[i+1], myarg) body['hidden'] = gam.getBoolean(sys.argv[i+1], myarg)
i += 2 i += 2
elif myarg == 'summary': elif myarg == 'summary':
body['summaryOverride'] = sys.argv[i+1] body['summaryOverride'] = sys.argv[i+1]
i += 2 i += 2
elif myarg == 'colorindex': elif myarg == 'colorindex':
body['colorId'] = __main__.getInteger( body['colorId'] = gam.getInteger(
sys.argv[i+1], myarg, minVal=CALENDAR_MIN_COLOR_INDEX, sys.argv[i+1], myarg, minVal=CALENDAR_MIN_COLOR_INDEX,
maxVal=CALENDAR_MAX_COLOR_INDEX) maxVal=CALENDAR_MAX_COLOR_INDEX)
i += 2 i += 2
elif myarg == 'backgroundcolor': elif myarg == 'backgroundcolor':
body['backgroundColor'] = __main__.getColor(sys.argv[i+1]) body['backgroundColor'] = gam.getColor(sys.argv[i+1])
colorRgbFormat = True colorRgbFormat = True
i += 2 i += 2
elif myarg == 'foregroundcolor': elif myarg == 'foregroundcolor':
body['foregroundColor'] = __main__.getColor(sys.argv[i+1]) body['foregroundColor'] = gam.getColor(sys.argv[i+1])
colorRgbFormat = True colorRgbFormat = True
i += 2 i += 2
elif myarg == 'reminder': elif myarg == 'reminder':
@ -677,7 +677,7 @@ def getCalendarAttributes(i, body, function):
if method not in CALENDAR_REMINDER_METHODS: if method not in CALENDAR_REMINDER_METHODS:
controlflow.expected_argument_exit("Method", ", ".join( controlflow.expected_argument_exit("Method", ", ".join(
CALENDAR_REMINDER_METHODS+CLEAR_NONE_ARGUMENT), method) CALENDAR_REMINDER_METHODS+CLEAR_NONE_ARGUMENT), method)
minutes = __main__.getInteger( minutes = gam.getInteger(
sys.argv[i+2], myarg, minVal=0, sys.argv[i+2], myarg, minVal=0,
maxVal=CALENDAR_REMINDER_MAX_MINUTES) maxVal=CALENDAR_REMINDER_MAX_MINUTES)
body['defaultReminders'].append( body['defaultReminders'].append(
@ -862,7 +862,7 @@ def transferSecCals(users):
remove_source_user = False remove_source_user = False
i += 1 i += 1
elif myarg == 'sendnotifications': elif myarg == 'sendnotifications':
sendNotifications = __main__.getBoolean(sys.argv[i+1], myarg) sendNotifications = gam.getBoolean(sys.argv[i+1], myarg)
i += 2 i += 2
else: else:
controlflow.invalid_argument_exit( controlflow.invalid_argument_exit(

View File

@ -0,0 +1,5 @@
import gam
def buildGAPIObject():
return gam.buildGAPIObject('directory')

View File

@ -1,17 +1,17 @@
import datetime import datetime
from var import * from gam.var import *
import __main__ import gam
import controlflow from gam import controlflow
import display from gam import display
import fileutils from gam import fileutils
import gapi from gam import gapi
import gapi.directory from gam.gapi import directory as gapi_directory
import utils from gam import utils
def doUpdateCros(): def doUpdateCros():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
i, devices = getCrOSDeviceEntity(3, cd) i, devices = getCrOSDeviceEntity(3, cd)
update_body = {} update_body = {}
action_body = {} action_body = {}
@ -32,7 +32,7 @@ def doUpdateCros():
update_body['annotatedAssetId'] = sys.argv[i+1] update_body['annotatedAssetId'] = sys.argv[i+1]
i += 2 i += 2
elif myarg in ['ou', 'org']: elif myarg in ['ou', 'org']:
orgUnitPath = __main__.getOrgUnitItem(sys.argv[i+1]) orgUnitPath = gam.getOrgUnitItem(sys.argv[i+1])
i += 2 i += 2
elif myarg == 'action': elif myarg == 'action':
action = sys.argv[i+1].lower().replace('_', '').replace('-', '') action = sys.argv[i+1].lower().replace('_', '').replace('-', '')
@ -84,7 +84,7 @@ def doUpdateCros():
sys.exit(3) sys.exit(3)
for deviceId in devices: for deviceId in devices:
i += 1 i += 1
cur_count = __main__.currentCount(i, count) cur_count = gam.currentCount(i, count)
print(f' performing action {action} for {deviceId}{cur_count}') print(f' performing action {action} for {deviceId}{cur_count}')
gapi.call(cd.chromeosdevices(), function='action', gapi.call(cd.chromeosdevices(), function='action',
customerId=GC_Values[GC_CUSTOMER_ID], customerId=GC_Values[GC_CUSTOMER_ID],
@ -93,7 +93,7 @@ def doUpdateCros():
if update_body: if update_body:
for deviceId in devices: for deviceId in devices:
i += 1 i += 1
current_count = __main__.currentCount(i, count) current_count = gam.currentCount(i, count)
print(f' updating {deviceId}{current_count}') print(f' updating {deviceId}{current_count}')
gapi.call(cd.chromeosdevices(), 'update', gapi.call(cd.chromeosdevices(), 'update',
customerId=GC_Values[GC_CUSTOMER_ID], customerId=GC_Values[GC_CUSTOMER_ID],
@ -110,7 +110,7 @@ def doUpdateCros():
def doGetCrosInfo(): def doGetCrosInfo():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
i, devices = getCrOSDeviceEntity(3, cd) i, devices = getCrOSDeviceEntity(3, cd)
downloadfile = None downloadfile = None
targetFolder = GC_Values[GC_DRIVE_DIR] targetFolder = GC_Values[GC_DRIVE_DIR]
@ -125,7 +125,7 @@ def doGetCrosInfo():
noLists = True noLists = True
i += 1 i += 1
elif myarg == 'listlimit': elif myarg == 'listlimit':
listLimit = __main__.getInteger(sys.argv[i+1], myarg, minVal=-1) listLimit = gam.getInteger(sys.argv[i+1], myarg, minVal=-1)
i += 2 i += 2
elif myarg in CROS_START_ARGUMENTS: elif myarg in CROS_START_ARGUMENTS:
startDate = _getFilterDate(sys.argv[i+1]) startDate = _getFilterDate(sys.argv[i+1])
@ -318,7 +318,7 @@ def doGetCrosInfo():
def doPrintCrosActivity(): def doPrintCrosActivity():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
todrive = False todrive = False
titles = ['deviceId', 'annotatedAssetId', titles = ['deviceId', 'annotatedAssetId',
'annotatedLocation', 'serialNumber', 'orgUnitPath'] 'annotatedLocation', 'serialNumber', 'orgUnitPath']
@ -335,10 +335,10 @@ def doPrintCrosActivity():
while i < len(sys.argv): while i < len(sys.argv):
myarg = sys.argv[i].lower().replace('_', '') myarg = sys.argv[i].lower().replace('_', '')
if myarg in ['query', 'queries']: if myarg in ['query', 'queries']:
queries = __main__.getQueries(myarg, sys.argv[i+1]) queries = gam.getQueries(myarg, sys.argv[i+1])
i += 2 i += 2
elif myarg == 'limittoou': elif myarg == 'limittoou':
orgUnitPath = __main__.getOrgUnitItem(sys.argv[i+1]) orgUnitPath = gam.getOrgUnitItem(sys.argv[i+1])
i += 2 i += 2
elif myarg == 'todrive': elif myarg == 'todrive':
todrive = True todrive = True
@ -366,7 +366,7 @@ def doPrintCrosActivity():
endDate = _getFilterDate(sys.argv[i+1]) endDate = _getFilterDate(sys.argv[i+1])
i += 2 i += 2
elif myarg == 'listlimit': elif myarg == 'listlimit':
listLimit = __main__.getInteger(sys.argv[i+1], myarg, minVal=0) listLimit = gam.getInteger(sys.argv[i+1], myarg, minVal=0)
i += 2 i += 2
elif myarg == 'delimiter': elif myarg == 'delimiter':
delimiter = sys.argv[i+1] delimiter = sys.argv[i+1]
@ -393,7 +393,7 @@ def doPrintCrosActivity():
display.add_titles_to_csv_file(titles_to_add, titles) display.add_titles_to_csv_file(titles_to_add, titles)
fields = f'nextPageToken,chromeosdevices({",".join(fieldsList)})' fields = f'nextPageToken,chromeosdevices({",".join(fieldsList)})'
for query in queries: for query in queries:
__main__.printGettingAllItems('CrOS Devices', query) gam.printGettingAllItems('CrOS Devices', query)
page_message = gapi.got_total_items_msg('CrOS Devices', '...\n') page_message = gapi.got_total_items_msg('CrOS Devices', '...\n')
all_cros = gapi.get_all_pages(cd.chromeosdevices(), 'list', all_cros = gapi.get_all_pages(cd.chromeosdevices(), 'list',
'chromeosdevices', 'chromeosdevices',
@ -479,7 +479,7 @@ def doPrintCrosDevices():
elif myarg in CROS_SYSTEM_RAM_FREE_REPORTS_ARGUMENTS: elif myarg in CROS_SYSTEM_RAM_FREE_REPORTS_ARGUMENTS:
selectedLists['systemRamFreeReports'] = True selectedLists['systemRamFreeReports'] = True
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
todrive = False todrive = False
fieldsList = [] fieldsList = []
fieldsTitles = {} fieldsTitles = {}
@ -497,10 +497,10 @@ def doPrintCrosDevices():
while i < len(sys.argv): while i < len(sys.argv):
myarg = sys.argv[i].lower().replace('_', '') myarg = sys.argv[i].lower().replace('_', '')
if myarg in ['query', 'queries']: if myarg in ['query', 'queries']:
queries = __main__.getQueries(myarg, sys.argv[i+1]) queries = gam.getQueries(myarg, sys.argv[i+1])
i += 2 i += 2
elif myarg == 'limittoou': elif myarg == 'limittoou':
orgUnitPath = __main__.getOrgUnitItem(sys.argv[i+1]) orgUnitPath = gam.getOrgUnitItem(sys.argv[i+1])
i += 2 i += 2
elif myarg == 'todrive': elif myarg == 'todrive':
todrive = True todrive = True
@ -510,7 +510,7 @@ def doPrintCrosDevices():
selectedLists = {} selectedLists = {}
i += 1 i += 1
elif myarg == 'listlimit': elif myarg == 'listlimit':
listLimit = __main__.getInteger(sys.argv[i+1], myarg, minVal=0) listLimit = gam.getInteger(sys.argv[i+1], myarg, minVal=0)
i += 2 i += 2
elif myarg in CROS_START_ARGUMENTS: elif myarg in CROS_START_ARGUMENTS:
startDate = _getFilterDate(sys.argv[i+1]) startDate = _getFilterDate(sys.argv[i+1])
@ -589,7 +589,7 @@ def doPrintCrosDevices():
else: else:
fields = None fields = None
for query in queries: for query in queries:
__main__.printGettingAllItems('CrOS Devices', query) gam.printGettingAllItems('CrOS Devices', query)
page_message = gapi.got_total_items_msg('CrOS Devices', '...\n') page_message = gapi.got_total_items_msg('CrOS Devices', '...\n')
all_cros = gapi.get_all_pages(cd.chromeosdevices(), 'list', all_cros = gapi.get_all_pages(cd.chromeosdevices(), 'list',
'chromeosdevices', 'chromeosdevices',
@ -742,9 +742,9 @@ def doPrintCrosDevices():
def getCrOSDeviceEntity(i, cd): def getCrOSDeviceEntity(i, cd):
myarg = sys.argv[i].lower() myarg = sys.argv[i].lower()
if myarg == 'cros_sn': if myarg == 'cros_sn':
return i+2, __main__.getUsersToModify('cros_sn', sys.argv[i+1]) return i+2, gam.getUsersToModify('cros_sn', sys.argv[i+1])
if myarg == 'query': if myarg == 'query':
return i+2, __main__.getUsersToModify('crosquery', sys.argv[i+1]) return i+2, gam.getUsersToModify('crosquery', sys.argv[i+1])
if myarg[:6] == 'query:': if myarg[:6] == 'query:':
query = sys.argv[i][6:] query = sys.argv[i][6:]
if query[:12].lower() == 'orgunitpath:': if query[:12].lower() == 'orgunitpath:':

View File

@ -1,14 +1,14 @@
import datetime import datetime
from var import * from gam.var import *
import controlflow from gam import controlflow
import gapi from gam import gapi
import gapi.directory from gam.gapi import directory as gapi_directory
import gapi.reports from gam.gapi import reports as gapi_reports
def doGetCustomerInfo(): def doGetCustomerInfo():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
customer_info = gapi.call(cd.customers(), 'get', customer_info = gapi.call(cd.customers(), 'get',
customerKey=GC_Values[GC_CUSTOMER_ID]) customerKey=GC_Values[GC_CUSTOMER_ID])
print(f'Customer ID: {customer_info["id"]}') print(f'Customer ID: {customer_info["id"]}')
@ -59,7 +59,7 @@ def doGetCustomerInfo():
customerId = GC_Values[GC_CUSTOMER_ID] customerId = GC_Values[GC_CUSTOMER_ID]
if customerId == MY_CUSTOMER: if customerId == MY_CUSTOMER:
customerId = None customerId = None
rep = gapi.reports.buildGAPIObject() rep = gapi_reports.buildGAPIObject()
usage = None usage = None
throw_reasons = [gapi.errors.ErrorReason.INVALID] throw_reasons = [gapi.errors.ErrorReason.INVALID]
while True: while True:
@ -71,7 +71,7 @@ def doGetCustomerInfo():
parameters=parameters) parameters=parameters)
break break
except gapi.errors.GapiInvalidError as e: except gapi.errors.GapiInvalidError as e:
tryDate = gapi.reports._adjust_date(str(e)) tryDate = gapi_reports._adjust_date(str(e))
if not usage: if not usage:
print('No user count data available.') print('No user count data available.')
return return
@ -84,7 +84,7 @@ def doGetCustomerInfo():
def doUpdateCustomer(): def doUpdateCustomer():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
body = {} body = {}
i = 3 i = 3
while i < len(sys.argv): while i < len(sys.argv):

View File

@ -1,17 +1,18 @@
import sys import sys
import uuid import uuid
import __main__ import gam
from var import * from gam.var import *
import controlflow from gam import controlflow
import display from gam import display
import gapi.directory from gam import gapi
import utils from gam.gapi import directory as gapi_directory
from gam import utils
def printBuildings(): def printBuildings():
to_drive = False to_drive = False
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
titles = [] titles = []
csvRows = [] csvRows = []
fieldsList = ['buildingId'] fieldsList = ['buildingId']
@ -65,7 +66,7 @@ def printBuildings():
def printResourceCalendars(): def printResourceCalendars():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
todrive = False todrive = False
fieldsList = [] fieldsList = []
fieldsTitles = {} fieldsTitles = {}
@ -108,7 +109,7 @@ def printResourceCalendars():
if 'buildingId' in fieldsList: if 'buildingId' in fieldsList:
display.add_field_to_csv_file('buildingName', {'buildingName': [ display.add_field_to_csv_file('buildingName', {'buildingName': [
'buildingName', ]}, fieldsList, fieldsTitles, titles) 'buildingName', ]}, fieldsList, fieldsTitles, titles)
__main__.printGettingAllItems('Resource Calendars', None) gam.printGettingAllItems('Resource Calendars', None)
page_message = gapi.got_total_items_first_last_msg('Resource Calendars') page_message = gapi.got_total_items_first_last_msg('Resource Calendars')
resources = gapi.get_all_pages(cd.resources().calendars(), 'list', resources = gapi.get_all_pages(cd.resources().calendars(), 'list',
'items', page_message=page_message, 'items', page_message=page_message,
@ -162,7 +163,7 @@ RESCAL_ARGUMENT_TO_PROPERTY_MAP = {
def printFeatures(): def printFeatures():
to_drive = False to_drive = False
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
titles = [] titles = []
csvRows = [] csvRows = []
fieldsList = ['name'] fieldsList = ['name']
@ -240,7 +241,7 @@ def _getBuildingAttributes(args, body={}):
def createBuilding(): def createBuilding():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
body = {'floorNames': ['1'], body = {'floorNames': ['1'],
'buildingId': str(uuid.uuid4()), 'buildingId': str(uuid.uuid4()),
'buildingName': sys.argv[3]} 'buildingName': sys.argv[3]}
@ -318,7 +319,7 @@ def getBuildingNameById(cd, buildingId):
def updateBuilding(): def updateBuilding():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
buildingId = getBuildingByNameOrId(cd, sys.argv[3]) buildingId = getBuildingByNameOrId(cd, sys.argv[3])
body = _getBuildingAttributes(sys.argv[4:]) body = _getBuildingAttributes(sys.argv[4:])
print(f'Updating building {buildingId}...') print(f'Updating building {buildingId}...')
@ -328,7 +329,7 @@ def updateBuilding():
def getBuildingInfo(): def getBuildingInfo():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
buildingId = getBuildingByNameOrId(cd, sys.argv[3]) buildingId = getBuildingByNameOrId(cd, sys.argv[3])
building = gapi.call(cd.resources().buildings(), 'get', building = gapi.call(cd.resources().buildings(), 'get',
customer=GC_Values[GC_CUSTOMER_ID], customer=GC_Values[GC_CUSTOMER_ID],
@ -343,7 +344,7 @@ def getBuildingInfo():
def deleteBuilding(): def deleteBuilding():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
buildingId = getBuildingByNameOrId(cd, sys.argv[3]) buildingId = getBuildingByNameOrId(cd, sys.argv[3])
print(f'Deleting building {buildingId}...') print(f'Deleting building {buildingId}...')
gapi.call(cd.resources().buildings(), 'delete', gapi.call(cd.resources().buildings(), 'delete',
@ -364,7 +365,7 @@ def _getFeatureAttributes(args, body={}):
def createFeature(): def createFeature():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
body = _getFeatureAttributes(sys.argv[3:]) body = _getFeatureAttributes(sys.argv[3:])
print(f'Creating feature {body["name"]}...') print(f'Creating feature {body["name"]}...')
gapi.call(cd.resources().features(), 'insert', gapi.call(cd.resources().features(), 'insert',
@ -375,7 +376,7 @@ def updateFeature():
# update does not work for name and name is only field to be updated # update does not work for name and name is only field to be updated
# if additional writable fields are added to feature in the future # if additional writable fields are added to feature in the future
# we'll add support for update as well as rename # we'll add support for update as well as rename
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
oldName = sys.argv[3] oldName = sys.argv[3]
body = {'newName': sys.argv[5:]} body = {'newName': sys.argv[5:]}
print(f'Updating feature {oldName}...') print(f'Updating feature {oldName}...')
@ -385,7 +386,7 @@ def updateFeature():
def deleteFeature(): def deleteFeature():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
featureKey = sys.argv[3] featureKey = sys.argv[3]
print(f'Deleting feature {featureKey}...') print(f'Deleting feature {featureKey}...')
gapi.call(cd.resources().features(), 'delete', gapi.call(cd.resources().features(), 'delete',
@ -410,7 +411,7 @@ def _getResourceCalendarAttributes(cd, args, body={}):
cd, args[i+1], minLen=0) cd, args[i+1], minLen=0)
i += 2 i += 2
elif myarg in ['capacity']: elif myarg in ['capacity']:
body['capacity'] = __main__.getInteger(args[i+1], myarg, minVal=0) body['capacity'] = gam.getInteger(args[i+1], myarg, minVal=0)
i += 2 i += 2
elif myarg in ['feature', 'features']: elif myarg in ['feature', 'features']:
features = args[i+1].split(',') features = args[i+1].split(',')
@ -440,7 +441,7 @@ def _getResourceCalendarAttributes(cd, args, body={}):
def createResourceCalendar(): def createResourceCalendar():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
body = {'resourceId': sys.argv[3], body = {'resourceId': sys.argv[3],
'resourceName': sys.argv[4]} 'resourceName': sys.argv[4]}
body = _getResourceCalendarAttributes(cd, sys.argv[5:], body) body = _getResourceCalendarAttributes(cd, sys.argv[5:], body)
@ -450,7 +451,7 @@ def createResourceCalendar():
def updateResourceCalendar(): def updateResourceCalendar():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
resId = sys.argv[3] resId = sys.argv[3]
body = _getResourceCalendarAttributes(cd, sys.argv[4:]) body = _getResourceCalendarAttributes(cd, sys.argv[4:])
# Use patch since it seems to work better. # Use patch since it seems to work better.
@ -462,7 +463,7 @@ def updateResourceCalendar():
def getResourceCalendarInfo(): def getResourceCalendarInfo():
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
resId = sys.argv[3] resId = sys.argv[3]
resource = gapi.call(cd.resources().calendars(), 'get', resource = gapi.call(cd.resources().calendars(), 'get',
customer=GC_Values[GC_CUSTOMER_ID], customer=GC_Values[GC_CUSTOMER_ID],
@ -481,7 +482,7 @@ def getResourceCalendarInfo():
def deleteResourceCalendar(): def deleteResourceCalendar():
resId = sys.argv[3] resId = sys.argv[3]
cd = gapi.directory.buildGAPIObject() cd = gapi_directory.buildGAPIObject()
print(f'Deleting resource calendar {resId}') print(f'Deleting resource calendar {resId}')
gapi.call(cd.resources().calendars(), 'delete', gapi.call(cd.resources().calendars(), 'delete',
customer=GC_Values[GC_CUSTOMER_ID], calendarResourceId=resId) customer=GC_Values[GC_CUSTOMER_ID], calendarResourceId=resId)

View File

@ -3,9 +3,9 @@
from enum import Enum from enum import Enum
import json import json
import controlflow from gam import controlflow
import display # TODO: Change to relative import when gam is setup as a package from gam import display
from var import UTF8 from gam.var import UTF8
class GapiAbortedError(Exception): class GapiAbortedError(Exception):

View File

@ -6,7 +6,7 @@ import unittest
from unittest.mock import patch from unittest.mock import patch
import googleapiclient.errors import googleapiclient.errors
from gapi import errors from gam.gapi import errors
def create_simple_http_error(status, reason, message): def create_simple_http_error(status, reason, message):

View File

@ -5,16 +5,16 @@ import sys
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
import __main__ import gam
from var import * from gam.var import *
import controlflow from gam import controlflow
import display from gam import display
import gapi from gam import gapi
import utils from gam import utils
def buildGAPIObject(): def buildGAPIObject():
return __main__.buildGAPIObject('reports') return gam.buildGAPIObject('reports')
REPORT_CHOICE_MAP = { REPORT_CHOICE_MAP = {
@ -55,7 +55,7 @@ def showUsageParameters():
kwargs = {} kwargs = {}
elif report == 'user': elif report == 'user':
endpoint = rep.userUsageReport() endpoint = rep.userUsageReport()
kwargs = {'userKey': __main__._getValueFromOAuth('email')} kwargs = {'userKey': gam._getValueFromOAuth('email')}
else: else:
controlflow.expected_argument_exit( controlflow.expected_argument_exit(
'usageparameters', ['user', 'customer'], report) 'usageparameters', ['user', 'customer'], report)
@ -170,10 +170,10 @@ def showUsage():
skip_day_numbers = [dow.index(d) for d in skipdaynames if d in dow] skip_day_numbers = [dow.index(d) for d in skipdaynames if d in dow]
i += 2 i += 2
elif report == 'user' and myarg in ['orgunit', 'org', 'ou']: elif report == 'user' and myarg in ['orgunit', 'org', 'ou']:
_, orgUnitId = __main__.getOrgUnitId(sys.argv[i+1]) _, orgUnitId = gam.getOrgUnitId(sys.argv[i+1])
i += 2 i += 2
elif report == 'user' and myarg in usergroup_types: elif report == 'user' and myarg in usergroup_types:
users = __main__.getUsersToModify(myarg, sys.argv[i+1]) users = gam.getUsersToModify(myarg, sys.argv[i+1])
kwargs = [{'userKey': user} for user in users] kwargs = [{'userKey': user} for user in users]
i += 2 i += 2
else: else:
@ -286,7 +286,7 @@ def showReport():
tryDate = utils.get_yyyymmdd(sys.argv[i+1]) tryDate = utils.get_yyyymmdd(sys.argv[i+1])
i += 2 i += 2
elif myarg in ['orgunit', 'org', 'ou']: elif myarg in ['orgunit', 'org', 'ou']:
_, orgUnitId = __main__.getOrgUnitId(sys.argv[i+1]) _, orgUnitId = gam.getOrgUnitId(sys.argv[i+1])
i += 2 i += 2
elif myarg == 'fulldatarequired': elif myarg == 'fulldatarequired':
fullDataRequired = [] fullDataRequired = []
@ -304,7 +304,7 @@ def showReport():
eventName = sys.argv[i+1] eventName = sys.argv[i+1]
i += 2 i += 2
elif myarg == 'user': elif myarg == 'user':
userKey = __main__.normalizeEmailAddressOrUID(sys.argv[i+1]) userKey = gam.normalizeEmailAddressOrUID(sys.argv[i+1])
i += 2 i += 2
elif myarg in ['filter', 'filters']: elif myarg in ['filter', 'filters']:
filters = sys.argv[i+1] filters = sys.argv[i+1]

View File

@ -5,16 +5,15 @@ import sys
import googleapiclient import googleapiclient
import __main__ import gam
from var import * from gam.var import *
import controlflow from gam import fileutils
import fileutils from gam import gapi
import gapi from gam import utils
import utils
def build_gapi(): def build_gapi():
return __main__.buildGAPIObject('storage') return gam.buildGAPIObject('storage')
def get_cloud_storage_object(s, bucket, object_, local_file=None, def get_cloud_storage_object(s, bucket, object_, local_file=None,

View File

@ -4,24 +4,24 @@ import sys
import googleapiclient.http import googleapiclient.http
import __main__ import gam
from var import * from gam.var import *
import controlflow from gam import controlflow
import display from gam import display
import fileutils from gam import fileutils
import gapi from gam import gapi
import gapi.storage from gam.gapi import storage as gapi_storage
import utils from gam import utils
def buildGAPIObject(): def buildGAPIObject():
return __main__.buildGAPIObject('vault') return gam.buildGAPIObject('vault')
def validateCollaborators(collaboratorList, cd): def validateCollaborators(collaboratorList, cd):
collaborators = [] collaborators = []
for collaborator in collaboratorList.split(','): for collaborator in collaboratorList.split(','):
collaborator_id = __main__.convertEmailAddressToUID(collaborator, cd) collaborator_id = gam.convertEmailAddressToUID(collaborator, cd)
if not collaborator_id: if not collaborator_id:
controlflow.system_error_exit(4, f'failed to get a UID for ' controlflow.system_error_exit(4, f'failed to get a UID for '
f'{collaborator}. Please make ' f'{collaborator}. Please make '
@ -47,7 +47,7 @@ def createMatter():
i += 2 i += 2
elif myarg in ['collaborator', 'collaborators']: elif myarg in ['collaborator', 'collaborators']:
if not cd: if not cd:
cd = __main__.buildGAPIObject('directory') cd = gam.buildGAPIObject('directory')
collaborators.extend(validateCollaborators(sys.argv[i+1], cd)) collaborators.extend(validateCollaborators(sys.argv[i+1], cd))
i += 2 i += 2
else: else:
@ -124,7 +124,7 @@ def createExport():
i += 2 i += 2
elif searchMethod == 'ORG_UNIT': elif searchMethod == 'ORG_UNIT':
body['query']['orgUnitInfo'] = { body['query']['orgUnitInfo'] = {
'orgUnitId': __main__.getOrgUnitId(sys.argv[i+1])[1]} 'orgUnitId': gam.getOrgUnitId(sys.argv[i+1])[1]}
i += 2 i += 2
elif searchMethod == 'SHARED_DRIVE': elif searchMethod == 'SHARED_DRIVE':
body['query']['sharedDriveInfo'] = { body['query']['sharedDriveInfo'] = {
@ -158,7 +158,7 @@ def createExport():
i += 2 i += 2
elif myarg in ['excludedrafts']: elif myarg in ['excludedrafts']:
body['query']['mailOptions'] = { body['query']['mailOptions'] = {
'excludeDrafts': __main__.getBoolean(sys.argv[i+1], myarg)} 'excludeDrafts': gam.getBoolean(sys.argv[i+1], myarg)}
i += 2 i += 2
elif myarg in ['driveversiondate']: elif myarg in ['driveversiondate']:
body['query'].setdefault('driveOptions', {})['versionDate'] = \ body['query'].setdefault('driveOptions', {})['versionDate'] = \
@ -166,11 +166,11 @@ def createExport():
i += 2 i += 2
elif myarg in ['includeshareddrives', 'includeteamdrives']: elif myarg in ['includeshareddrives', 'includeteamdrives']:
body['query'].setdefault('driveOptions', {})[ body['query'].setdefault('driveOptions', {})[
'includeSharedDrives'] = __main__.getBoolean(sys.argv[i+1], myarg) 'includeSharedDrives'] = gam.getBoolean(sys.argv[i+1], myarg)
i += 2 i += 2
elif myarg in ['includerooms']: elif myarg in ['includerooms']:
body['query']['hangoutsChatOptions'] = { body['query']['hangoutsChatOptions'] = {
'includeRooms': __main__.getBoolean(sys.argv[i+1], myarg)} 'includeRooms': gam.getBoolean(sys.argv[i+1], myarg)}
i += 2 i += 2
elif myarg in ['format']: elif myarg in ['format']:
export_format = sys.argv[i+1].upper() export_format = sys.argv[i+1].upper()
@ -179,7 +179,7 @@ def createExport():
"export format", ", ".join(allowed_formats), export_format) "export format", ", ".join(allowed_formats), export_format)
i += 2 i += 2
elif myarg in ['showconfidentialmodecontent']: elif myarg in ['showconfidentialmodecontent']:
showConfidentialModeContent = __main__.getBoolean(sys.argv[i+1], myarg) showConfidentialModeContent = gam.getBoolean(sys.argv[i+1], myarg)
i += 2 i += 2
elif myarg in ['region']: elif myarg in ['region']:
allowed_regions = gapi.get_enum_values_minus_unspecified( allowed_regions = gapi.get_enum_values_minus_unspecified(
@ -192,7 +192,7 @@ def createExport():
i += 2 i += 2
elif myarg in ['includeaccessinfo']: elif myarg in ['includeaccessinfo']:
body['exportOptions'].setdefault('driveOptions', {})[ body['exportOptions'].setdefault('driveOptions', {})[
'includeAccessInfo'] = __main__.getBoolean(sys.argv[i+1], myarg) 'includeAccessInfo'] = gam.getBoolean(sys.argv[i+1], myarg)
i += 2 i += 2
else: else:
controlflow.invalid_argument_exit(sys.argv[i], "gam create export") controlflow.invalid_argument_exit(sys.argv[i], "gam create export")
@ -277,7 +277,7 @@ def createHold():
i += 2 i += 2
elif myarg in ['orgunit', 'ou']: elif myarg in ['orgunit', 'ou']:
body['orgUnit'] = { body['orgUnit'] = {
'orgUnitId': __main__.getOrgUnitId(sys.argv[i+1])[1]} 'orgUnitId': gam.getOrgUnitId(sys.argv[i+1])[1]}
i += 2 i += 2
elif myarg in ['start', 'starttime']: elif myarg in ['start', 'starttime']:
start_time = utils.get_date_zero_time_or_full_time(sys.argv[i+1]) start_time = utils.get_date_zero_time_or_full_time(sys.argv[i+1])
@ -319,11 +319,11 @@ def createHold():
body['query'][query_type]['endTime'] = end_time body['query'][query_type]['endTime'] = end_time
if accounts: if accounts:
body['accounts'] = [] body['accounts'] = []
cd = __main__.buildGAPIObject('directory') cd = gam.buildGAPIObject('directory')
account_type = 'group' if body['corpus'] == 'GROUPS' else 'user' account_type = 'group' if body['corpus'] == 'GROUPS' else 'user'
for account in accounts: for account in accounts:
body['accounts'].append( body['accounts'].append(
{'accountId': __main__.convertEmailAddressToUID(account, {'accountId': gam.convertEmailAddressToUID(account,
cd, cd,
account_type)} account_type)}
) )
@ -370,16 +370,16 @@ def getHoldInfo():
3, 'you must specify a matter for the hold.') 3, 'you must specify a matter for the hold.')
results = gapi.call(v.matters().holds(), 'get', results = gapi.call(v.matters().holds(), 'get',
matterId=matterId, holdId=holdId) matterId=matterId, holdId=holdId)
cd = __main__.buildGAPIObject('directory') cd = gam.buildGAPIObject('directory')
if 'accounts' in results: if 'accounts' in results:
account_type = 'group' if results['corpus'] == 'GROUPS' else 'user' account_type = 'group' if results['corpus'] == 'GROUPS' else 'user'
for i in range(0, len(results['accounts'])): for i in range(0, len(results['accounts'])):
uid = f'uid:{results["accounts"][i]["accountId"]}' uid = f'uid:{results["accounts"][i]["accountId"]}'
acct_email = __main__.convertUIDtoEmailAddress( acct_email = gam.convertUIDtoEmailAddress(
uid, cd, [account_type]) uid, cd, [account_type])
results['accounts'][i]['email'] = acct_email results['accounts'][i]['email'] = acct_email
if 'orgUnit' in results: if 'orgUnit' in results:
results['orgUnit']['orgUnitPath'] = __main__.doGetOrgInfo( results['orgUnit']['orgUnitPath'] = gam.doGetOrgInfo(
results['orgUnit']['orgUnitId'], return_attrib='orgUnitPath') results['orgUnit']['orgUnitId'], return_attrib='orgUnitPath')
display.print_json(results) display.print_json(results)
@ -456,7 +456,7 @@ def updateHold():
query = sys.argv[i+1] query = sys.argv[i+1]
i += 2 i += 2
elif myarg in ['orgunit', 'ou']: elif myarg in ['orgunit', 'ou']:
body['orgUnit'] = {'orgUnitId': __main__.getOrgUnitId(sys.argv[i+1])[1]} body['orgUnit'] = {'orgUnitId': gam.getOrgUnitId(sys.argv[i+1])[1]}
i += 2 i += 2
elif myarg in ['start', 'starttime']: elif myarg in ['start', 'starttime']:
start_time = utils.get_date_zero_time_or_full_time(sys.argv[i+1]) start_time = utils.get_date_zero_time_or_full_time(sys.argv[i+1])
@ -505,15 +505,15 @@ def updateHold():
gapi.call(v.matters().holds(), 'update', gapi.call(v.matters().holds(), 'update',
matterId=matterId, holdId=holdId, body=body) matterId=matterId, holdId=holdId, body=body)
if add_accounts or del_accounts: if add_accounts or del_accounts:
cd = __main__.buildGAPIObject('directory') cd = gam.buildGAPIObject('directory')
for account in add_accounts: for account in add_accounts:
print(f'adding {account} to hold.') print(f'adding {account} to hold.')
add_body = {'accountId': __main__.convertEmailAddressToUID(account, cd)} add_body = {'accountId': gam.convertEmailAddressToUID(account, cd)}
gapi.call(v.matters().holds().accounts(), 'create', gapi.call(v.matters().holds().accounts(), 'create',
matterId=matterId, holdId=holdId, body=add_body) matterId=matterId, holdId=holdId, body=add_body)
for account in del_accounts: for account in del_accounts:
print(f'removing {account} from hold.') print(f'removing {account} from hold.')
accountId = __main__.convertEmailAddressToUID(account, cd) accountId = gam.convertEmailAddressToUID(account, cd)
gapi.call(v.matters().holds().accounts(), 'delete', gapi.call(v.matters().holds().accounts(), 'delete',
matterId=matterId, holdId=holdId, accountId=accountId) matterId=matterId, holdId=holdId, accountId=accountId)
@ -543,12 +543,12 @@ def updateMatter(action=None):
i += 2 i += 2
elif myarg in ['addcollaborator', 'addcollaborators']: elif myarg in ['addcollaborator', 'addcollaborators']:
if not cd: if not cd:
cd = __main__.buildGAPIObject('directory') cd = gam.buildGAPIObject('directory')
add_collaborators.extend(validateCollaborators(sys.argv[i+1], cd)) add_collaborators.extend(validateCollaborators(sys.argv[i+1], cd))
i += 2 i += 2
elif myarg in ['removecollaborator', 'removecollaborators']: elif myarg in ['removecollaborator', 'removecollaborators']:
if not cd: if not cd:
cd = __main__.buildGAPIObject('directory') cd = gam.buildGAPIObject('directory')
remove_collaborators.extend( remove_collaborators.extend(
validateCollaborators(sys.argv[i+1], cd)) validateCollaborators(sys.argv[i+1], cd))
i += 2 i += 2
@ -585,10 +585,10 @@ def getMatterInfo():
matterId = getMatterItem(v, sys.argv[3]) matterId = getMatterItem(v, sys.argv[3])
result = gapi.call(v.matters(), 'get', matterId=matterId, view='FULL') result = gapi.call(v.matters(), 'get', matterId=matterId, view='FULL')
if 'matterPermissions' in result: if 'matterPermissions' in result:
cd = __main__.buildGAPIObject('directory') cd = gam.buildGAPIObject('directory')
for i in range(0, len(result['matterPermissions'])): for i in range(0, len(result['matterPermissions'])):
uid = f'uid:{result["matterPermissions"][i]["accountId"]}' uid = f'uid:{result["matterPermissions"][i]["accountId"]}'
user_email = __main__.convertUIDtoEmailAddress(uid, cd) user_email = gam.convertUIDtoEmailAddress(uid, cd)
result['matterPermissions'][i]['email'] = user_email result['matterPermissions'][i]['email'] = user_email
display.print_json(result) display.print_json(result)
@ -597,7 +597,7 @@ def downloadExport():
verifyFiles = True verifyFiles = True
extractFiles = True extractFiles = True
v = buildGAPIObject() v = buildGAPIObject()
s = gapi.storage.build_gapi() s = gapi_storage.build_gapi()
matterId = getMatterItem(v, sys.argv[3]) matterId = getMatterItem(v, sys.argv[3])
exportId = convertExportNameToID(v, sys.argv[4], matterId) exportId = convertExportNameToID(v, sys.argv[4], matterId)
targetFolder = GC_Values[GC_DRIVE_DIR] targetFolder = GC_Values[GC_DRIVE_DIR]
@ -643,7 +643,7 @@ def downloadExport():
utils.md5_matches_file(filename, expected_hash, True) utils.md5_matches_file(filename, expected_hash, True)
print('VERIFIED') print('VERIFIED')
if extractFiles and re.search(r'\.zip$', filename): if extractFiles and re.search(r'\.zip$', filename):
__main__.extract_nested_zip(filename, targetFolder) gam.extract_nested_zip(filename, targetFolder)
def printMatters(): def printMatters():
@ -674,7 +674,7 @@ def printMatters():
i += 2 i += 2
else: else:
controlflow.invalid_argument_exit(myarg, "gam print matters") controlflow.invalid_argument_exit(myarg, "gam print matters")
__main__.printGettingAllItems('Vault Matters', None) gam.printGettingAllItems('Vault Matters', None)
page_message = gapi.got_total_items_msg('Vault Matters', '...\n') page_message = gapi.got_total_items_msg('Vault Matters', '...\n')
matters = gapi.get_all_pages( matters = gapi.get_all_pages(
v.matters(), 'list', 'matters', page_message=page_message, view=view, v.matters(), 'list', 'matters', page_message=page_message, view=view,

View File

@ -3,11 +3,11 @@
import google_auth_httplib2 import google_auth_httplib2
import httplib2 import httplib2
from var import GAM_INFO from gam.var import GAM_INFO
from var import GC_CA_FILE from gam.var import GC_CA_FILE
from var import GC_TLS_MAX_VERSION from gam.var import GC_TLS_MAX_VERSION
from var import GC_TLS_MIN_VERSION from gam.var import GC_TLS_MIN_VERSION
from var import GC_Values from gam.var import GC_Values
def create_http(cache=None, def create_http(cache=None,

View File

@ -8,7 +8,7 @@ from gam import SetGlobalVariables
import google_auth_httplib2 import google_auth_httplib2
import httplib2 import httplib2
import transport from gam import transport
class CreateHttpTest(unittest.TestCase): class CreateHttpTest(unittest.TestCase):

View File

@ -8,10 +8,10 @@ from html.parser import HTMLParser
import json import json
import dateutil.parser import dateutil.parser
import controlflow from gam import controlflow
import fileutils from gam import fileutils
import transport from gam import transport
from var import * from gam.var import *
class _DeHTMLParser(HTMLParser): class _DeHTMLParser(HTMLParser):

View File

@ -1,5 +0,0 @@
import __main__
def buildGAPIObject():
return __main__.buildGAPIObject('directory')

View File

@ -1,11 +1,11 @@
cd src cd src
if [[ "$TRAVIS_JOB_NAME" == *"Testing" ]]; then if [[ "$TRAVIS_JOB_NAME" == *"Testing" ]]; then
export gam="$python gam.py" export gam="$python -m gam"
export gampath=$(readlink -e .) export gampath=$(readlink -e .)
else else
$python -OO -m PyInstaller --clean --noupx --strip -F --distpath=gam gam.spec $python -OO -m PyInstaller --clean --noupx --strip -F gam.spec
export gam="gam/gam"
export gampath=$(readlink -e gam) export gampath=$(readlink -e gam)
export gam="${gampath}/gam"
export GAMVERSION=`$gam version simple` export GAMVERSION=`$gam version simple`
cp LICENSE $gampath cp LICENSE $gampath
cp whatsnew.txt $gampath cp whatsnew.txt $gampath
@ -13,21 +13,21 @@ else
this_glibc_ver=$(ldd --version | awk '/ldd/{print $NF}') this_glibc_ver=$(ldd --version | awk '/ldd/{print $NF}')
GAM_ARCHIVE=gam-$GAMVERSION-$GAMOS-$PLATFORM-glibc$this_glibc_ver.tar.xz GAM_ARCHIVE=gam-$GAMVERSION-$GAMOS-$PLATFORM-glibc$this_glibc_ver.tar.xz
rm $gampath/lastupdatecheck.txt rm $gampath/lastupdatecheck.txt
tar cfJ $GAM_ARCHIVE gam/ tar cfJ --transform s/dist/gam/ $GAM_ARCHIVE $gampath
echo "PyInstaller GAM info:" echo "PyInstaller GAM info:"
du -h gam/gam du -h $gam
time $gam version extended time $gam version extended
if ([ "${TRAVIS_DIST}" == "trusty" ] || [ "${TRAVIS_DIST}" == "xenial" ]) && [ "${PLATFORM}" == "x86_64" ]; then if [ "${TRAVIS_DIST}" == "xenial" ] && [ "${PLATFORM}" == "x86_64" ]; then
GAM_LEGACY_ARCHIVE=gam-${GAMVERSION}-${GAMOS}-${PLATFORM}-legacy.tar.xz GAM_LEGACY_ARCHIVE=gam-${GAMVERSION}-${GAMOS}-${PLATFORM}-legacy.tar.xz
$python -OO -m staticx -l /lib/x86_64-linux-gnu/libresolv.so.2 -l /lib/x86_64-linux-gnu/libnss_dns.so.2 gam/gam gam/gam-staticx $python -OO -m staticx -l /lib/x86_64-linux-gnu/libresolv.so.2 -l /lib/x86_64-linux-gnu/libnss_dns.so.2 $gam $gam-staticx
strip gam/gam-staticx strip $gam-staticx
rm gam/gam rm $gampath/gam
mv gam/gam-staticx gam/gam mv $gam-staticx $gam
chmod 755 gam/gam chmod 755 $gam
tar cvfJ $GAM_LEGACY_ARCHIVE gam/ tar cvfJ --transform s/dist/gam/ $GAM_LEGACY_ARCHIVE $gampath
echo "Legacy StaticX GAM info:" echo "Legacy StaticX GAM info:"
du -h gam/gam du -h $gam
time $gam version extended time $gam version extended
fi fi
echo "GAM packages:" echo "GAM packages:"

View File

@ -1,15 +1,15 @@
cd src cd src
echo "MacOS Version Info According to Python:" echo "MacOS Version Info According to Python:"
python -c "import platform; print(platform.mac_ver())" python -c "import platform; print(platform.mac_ver())"
$python -OO -m PyInstaller --clean --noupx --strip -F --distpath=gam gam.spec $python -OO -m PyInstaller --clean --noupx --strip -F gam.spec
export gam="gam/gam" export gampath=dist
export gampath=gam export gam="$gampath/gam"
$gam version extended $gam version extended
export GAMVERSION=`gam/gam version simple` export GAMVERSION=`$gam version simple`
cp LICENSE gam cp LICENSE $gampath
cp whatsnew.txt gam cp whatsnew.txt $gampath
cp GamCommands.txt gam cp GamCommands.txt $gampath
MACOSVERSION=$(defaults read loginwindow SystemVersionStampAsString) MACOSVERSION=$(defaults read loginwindow SystemVersionStampAsString)
GAM_ARCHIVE=gam-$GAMVERSION-$GAMOS-$PLATFORM-MacOS$MACOSVERSION.tar.xz GAM_ARCHIVE=gam-$GAMVERSION-$GAMOS-$PLATFORM-MacOS$MACOSVERSION.tar.xz
rm gam/lastupdatecheck.txt rm $gampath/lastupdatecheck.txt
tar cfJ $GAM_ARCHIVE gam/ tar cfJ $GAM_ARCHIVE --transform s/$gampath/gam $gampath

View File

@ -1,20 +1,21 @@
cd src cd src
echo "compiling GAM with pyinstaller..." echo "compiling GAM with pyinstaller..."
pyinstaller --clean --noupx -F --distpath=gam gam.spec pyinstaller --clean --noupx -F gam.spec
export gam="gam/gam"
export gampath=$(readlink -e gam) export gampath=$(readlink -e gam)
export gam="${gampath}/gam"
echo "running compiled GAM..." echo "running compiled GAM..."
$gam version $gam version
export GAMVERSION=`$gam version simple` export GAMVERSION=`$gam version simple`
rm gam/lastupdatecheck.txt rm $gampath/lastupdatecheck.txt
cp LICENSE gam cp LICENSE $gampath
cp GamCommands.txt gam cp GamCommands.txt $gampath
cp whatsnew.txt gam cp whatsnew.txt $gampath
cp gam-setup.bat gam cp gam-setup.bat $gampath
GAM_ARCHIVE=gam-$GAMVERSION-$GAMOS-$PLATFORM.zip GAM_ARCHIVE=gam-$GAMVERSION-$GAMOS-$PLATFORM.zip
/c/Program\ Files/7-Zip/7z.exe a -tzip $GAM_ARCHIVE gam -xr!.svn /c/Program\ Files/7-Zip/7z.exe a -tzip $GAM_ARCHIVE $gampath -xr!.svn
/c/Program\ Files/7-Zip/7z.exe rn $GAM_ARCHIVE dist\ gam\
mkdir gam-64 mkdir gam-64
cp -rf gam/* gam-64/; cp -rf $gampath/* gam-64/
/c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.11/bin/candle.exe -arch $WIX_BITS gam.wxs /c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.11/bin/candle.exe -arch $WIX_BITS gam.wxs
/c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.11/bin/light.exe -ext /c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.11/bin/WixUIExtension.dll gam.wixobj -o gam-$GAMVERSION-$GAMOS-$PLATFORM.msi || true; /c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.11/bin/light.exe -ext /c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.11/bin/WixUIExtension.dll gam.wixobj -o gam-$GAMVERSION-$GAMOS-$PLATFORM.msi || true;
rm *.wixpdb rm *.wixpdb